1 // Copyright (C) 2007-2015 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 // Author : Anthony Geay (CEA/DEN)
21 #include "MEDCouplingUMesh.hxx"
22 #include "MEDCoupling1GTUMesh.hxx"
23 #include "MEDCouplingMemArray.txx"
24 #include "MEDCouplingFieldDouble.hxx"
25 #include "MEDCouplingSkyLineArray.hxx"
26 #include "CellModel.hxx"
27 #include "VolSurfUser.txx"
28 #include "InterpolationUtils.hxx"
29 #include "PointLocatorAlgos.txx"
31 #include "BBTreeDst.txx"
32 #include "SplitterTetra.hxx"
33 #include "DiameterCalculator.hxx"
34 #include "DirectedBoundingBox.hxx"
35 #include "InterpKernelMatrixTools.hxx"
36 #include "InterpKernelMeshQuality.hxx"
37 #include "InterpKernelCellSimplify.hxx"
38 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
39 #include "InterpKernelAutoPtr.hxx"
40 #include "InterpKernelGeo2DNode.hxx"
41 #include "InterpKernelGeo2DEdgeLin.hxx"
42 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
43 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
52 using namespace ParaMEDMEM;
54 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
56 const INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::MEDMEM_ORDER[N_MEDMEM_ORDER] = { INTERP_KERNEL::NORM_POINT1, INTERP_KERNEL::NORM_SEG2, INTERP_KERNEL::NORM_SEG3, INTERP_KERNEL::NORM_SEG4, INTERP_KERNEL::NORM_POLYL, INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_TRI7, INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_QUAD9, INTERP_KERNEL::NORM_POLYGON, INTERP_KERNEL::NORM_QPOLYG, INTERP_KERNEL::NORM_TETRA4, INTERP_KERNEL::NORM_PYRA5, INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXA8, INTERP_KERNEL::NORM_HEXGP12, INTERP_KERNEL::NORM_TETRA10, INTERP_KERNEL::NORM_PYRA13, INTERP_KERNEL::NORM_PENTA15, INTERP_KERNEL::NORM_HEXA20, INTERP_KERNEL::NORM_HEXA27, INTERP_KERNEL::NORM_POLYHED };
58 MEDCouplingUMesh *MEDCouplingUMesh::New()
60 return new MEDCouplingUMesh;
63 MEDCouplingUMesh *MEDCouplingUMesh::New(const std::string& meshName, int meshDim)
65 MEDCouplingUMesh *ret=new MEDCouplingUMesh;
66 ret->setName(meshName);
67 ret->setMeshDimension(meshDim);
72 * Returns a new MEDCouplingMesh which is a full copy of \a this one. No data is shared
73 * between \a this and the new mesh.
74 * \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
75 * delete this mesh using decrRef() as it is no more needed.
77 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
83 * Returns a new MEDCouplingMesh which is a copy of \a this one.
84 * \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
85 * this mesh are shared by the new mesh.
86 * \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
87 * delete this mesh using decrRef() as it is no more needed.
89 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
91 return new MEDCouplingUMesh(*this,recDeepCpy);
95 * This method behaves mostly like MEDCouplingUMesh::deepCpy method, except that only nodal connectivity arrays are deeply copied.
96 * The coordinates are shared between \a this and the returned instance.
98 * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
99 * \sa MEDCouplingUMesh::deepCpy
101 MEDCouplingPointSet *MEDCouplingUMesh::deepCpyConnectivityOnly() const
103 checkConnectivityFullyDefined();
104 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=clone(false);
105 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(getNodalConnectivity()->deepCpy()),ci(getNodalConnectivityIndex()->deepCpy());
106 ret->setConnectivity(c,ci);
110 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other)
113 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
114 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
116 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
117 MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
118 setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
121 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
123 std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
127 std::vector<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildrenWithNull() const
129 std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildrenWithNull());
130 ret.push_back(_nodal_connec);
131 ret.push_back(_nodal_connec_index);
135 void MEDCouplingUMesh::updateTime() const
137 MEDCouplingPointSet::updateTime();
140 updateTimeWith(*_nodal_connec);
142 if(_nodal_connec_index)
144 updateTimeWith(*_nodal_connec_index);
148 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
153 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
154 * then \a this mesh is most probably is writable, exchangeable and available for most
155 * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
156 * this method to check that all is in order with \a this mesh.
157 * \throw If the mesh dimension is not set.
158 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
159 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
160 * \throw If the connectivity data array has more than one component.
161 * \throw If the connectivity data array has a named component.
162 * \throw If the connectivity index data array has more than one component.
163 * \throw If the connectivity index data array has a named component.
165 void MEDCouplingUMesh::checkCoherency() const
168 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
170 MEDCouplingPointSet::checkCoherency();
171 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
173 if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
175 std::ostringstream message;
176 message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
177 throw INTERP_KERNEL::Exception(message.str().c_str());
182 if(_nodal_connec->getNumberOfComponents()!=1)
183 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
184 if(_nodal_connec->getInfoOnComponent(0)!="")
185 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
189 throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
190 if(_nodal_connec_index)
192 if(_nodal_connec_index->getNumberOfComponents()!=1)
193 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
194 if(_nodal_connec_index->getInfoOnComponent(0)!="")
195 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
199 throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
203 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
204 * then \a this mesh is most probably is writable, exchangeable and available for all
205 * algorithms. <br> In addition to the checks performed by checkCoherency(), this
206 * method thoroughly checks the nodal connectivity.
207 * \param [in] eps - a not used parameter.
208 * \throw If the mesh dimension is not set.
209 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
210 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
211 * \throw If the connectivity data array has more than one component.
212 * \throw If the connectivity data array has a named component.
213 * \throw If the connectivity index data array has more than one component.
214 * \throw If the connectivity index data array has a named component.
215 * \throw If number of nodes defining an element does not correspond to the type of element.
216 * \throw If the nodal connectivity includes an invalid node id.
218 void MEDCouplingUMesh::checkCoherency1(double eps) const
223 int meshDim=getMeshDimension();
224 int nbOfNodes=getNumberOfNodes();
225 int nbOfCells=getNumberOfCells();
226 const int *ptr=_nodal_connec->getConstPointer();
227 const int *ptrI=_nodal_connec_index->getConstPointer();
228 for(int i=0;i<nbOfCells;i++)
230 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
231 if((int)cm.getDimension()!=meshDim)
233 std::ostringstream oss;
234 oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
235 throw INTERP_KERNEL::Exception(oss.str().c_str());
237 int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
239 if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
241 std::ostringstream oss;
242 oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " << cm.getNumberOfNodes();
243 oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
244 throw INTERP_KERNEL::Exception(oss.str().c_str());
246 if(cm.isQuadratic() && cm.isDynamic() && meshDim == 2)
247 if (nbOfNodesInCell % 2 || nbOfNodesInCell < 4)
249 std::ostringstream oss;
250 oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with quadratic type '" << cm.getRepr() << "' has " << nbOfNodesInCell;
251 oss << " nodes. This should be even, and greater or equal than 4!! Looks very bad!";
252 throw INTERP_KERNEL::Exception(oss.str().c_str());
254 for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
259 if(nodeId>=nbOfNodes)
261 std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes in the mesh !";
262 throw INTERP_KERNEL::Exception(oss.str().c_str());
267 std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " in connectivity ! sounds bad !";
268 throw INTERP_KERNEL::Exception(oss.str().c_str());
272 if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
274 std::ostringstream oss; oss << "Cell #" << i << " is built with node #-1 in connectivity ! sounds bad !";
275 throw INTERP_KERNEL::Exception(oss.str().c_str());
284 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
285 * then \a this mesh is most probably is writable, exchangeable and available for all
286 * algorithms. <br> This method performs the same checks as checkCoherency1() does.
287 * \param [in] eps - a not used parameter.
288 * \throw If the mesh dimension is not set.
289 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
290 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
291 * \throw If the connectivity data array has more than one component.
292 * \throw If the connectivity data array has a named component.
293 * \throw If the connectivity index data array has more than one component.
294 * \throw If the connectivity index data array has a named component.
295 * \throw If number of nodes defining an element does not correspond to the type of element.
296 * \throw If the nodal connectivity includes an invalid node id.
298 void MEDCouplingUMesh::checkCoherency2(double eps) const
300 checkCoherency1(eps);
304 * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
305 * elements contained in the mesh. For more info on the mesh dimension see
306 * \ref MEDCouplingUMeshPage.
307 * \param [in] meshDim - a new mesh dimension.
308 * \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
310 void MEDCouplingUMesh::setMeshDimension(int meshDim)
312 if(meshDim<-1 || meshDim>3)
313 throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
319 * Allocates memory to store an estimation of the given number of cells. The closer is the estimation to the number of cells effectively inserted,
320 * the less will the library need to reallocate memory. If the number of cells to be inserted is not known simply put 0 to this parameter.
321 * If a nodal connectivity previouly existed before the call of this method, it will be reset.
323 * \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
325 * \if ENABLE_EXAMPLES
326 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
327 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
330 void MEDCouplingUMesh::allocateCells(int nbOfCells)
333 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
334 if(_nodal_connec_index)
336 _nodal_connec_index->decrRef();
340 _nodal_connec->decrRef();
342 _nodal_connec_index=DataArrayInt::New();
343 _nodal_connec_index->reserve(nbOfCells+1);
344 _nodal_connec_index->pushBackSilent(0);
345 _nodal_connec=DataArrayInt::New();
346 _nodal_connec->reserve(2*nbOfCells);
352 * Appends a cell to the connectivity array. For deeper understanding what is
353 * happening see \ref MEDCouplingUMeshNodalConnectivity.
354 * \param [in] type - type of cell to add.
355 * \param [in] size - number of nodes constituting this cell.
356 * \param [in] nodalConnOfCell - the connectivity of the cell to add.
358 * \if ENABLE_EXAMPLES
359 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
360 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
363 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
365 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
366 if(_nodal_connec_index==0)
367 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
368 if((int)cm.getDimension()==_mesh_dim)
371 if(size!=(int)cm.getNumberOfNodes())
373 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
374 oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
375 throw INTERP_KERNEL::Exception(oss.str().c_str());
377 int idx=_nodal_connec_index->back();
379 _nodal_connec_index->pushBackSilent(val);
380 _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
385 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
386 oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
387 oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
388 throw INTERP_KERNEL::Exception(oss.str().c_str());
393 * Compacts data arrays to release unused memory. This method is to be called after
394 * finishing cell insertion using \a this->insertNextCell().
396 * \if ENABLE_EXAMPLES
397 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
398 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
401 void MEDCouplingUMesh::finishInsertingCells()
403 _nodal_connec->pack();
404 _nodal_connec_index->pack();
405 _nodal_connec->declareAsNew();
406 _nodal_connec_index->declareAsNew();
411 * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
412 * Useful for python users.
414 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
416 return new MEDCouplingUMeshCellIterator(this);
420 * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
421 * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
422 * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
423 * Useful for python users.
425 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
427 if(!checkConsecutiveCellTypes())
428 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
429 return new MEDCouplingUMeshCellByTypeEntry(this);
433 * Returns a set of all cell types available in \a this mesh.
434 * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
435 * \warning this method does not throw any exception even if \a this is not defined.
436 * \sa MEDCouplingUMesh::getAllGeoTypesSorted
438 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
444 * This method returns the sorted list of geometric types in \a this.
445 * Sorted means in the same order than the cells in \a this. A single entry in return vector means the maximal chunk of consecutive cells in \a this
446 * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
448 * \throw if connectivity in \a this is not correctly defined.
450 * \sa MEDCouplingMesh::getAllGeoTypes
452 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
454 std::vector<INTERP_KERNEL::NormalizedCellType> ret;
455 checkConnectivityFullyDefined();
456 int nbOfCells(getNumberOfCells());
459 if(getMeshLength()<1)
460 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
461 const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
462 ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
463 for(int i=1;i<nbOfCells;i++,ci++)
464 if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
465 ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
470 * This method is a method that compares \a this and \a other.
471 * This method compares \b all attributes, even names and component names.
473 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
476 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
477 std::ostringstream oss; oss.precision(15);
478 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
481 reason="mesh given in input is not castable in MEDCouplingUMesh !";
484 if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
486 if(_mesh_dim!=otherC->_mesh_dim)
488 oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" << otherC->_mesh_dim;
492 if(_types!=otherC->_types)
494 oss << "umesh geometric type mismatch :\nThis geometric types are :";
495 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
496 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
497 oss << "\nOther geometric types are :";
498 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
499 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
503 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
504 if(_nodal_connec==0 || otherC->_nodal_connec==0)
506 reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
509 if(_nodal_connec!=otherC->_nodal_connec)
510 if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
512 reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
515 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
516 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
518 reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
521 if(_nodal_connec_index!=otherC->_nodal_connec_index)
522 if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
524 reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
531 * Checks if data arrays of this mesh (node coordinates, nodal
532 * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
534 * \param [in] other - the mesh to compare with.
535 * \param [in] prec - precision value used to compare node coordinates.
536 * \return bool - \a true if the two meshes are same.
538 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
540 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
543 if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
545 if(_mesh_dim!=otherC->_mesh_dim)
547 if(_types!=otherC->_types)
549 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
550 if(_nodal_connec==0 || otherC->_nodal_connec==0)
552 if(_nodal_connec!=otherC->_nodal_connec)
553 if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
555 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
556 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
558 if(_nodal_connec_index!=otherC->_nodal_connec_index)
559 if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
565 * Checks if \a this and \a other meshes are geometrically equivalent with high
566 * probability, else an exception is thrown. The meshes are considered equivalent if
567 * (1) meshes contain the same number of nodes and the same number of elements of the
568 * same types (2) three cells of the two meshes (first, last and middle) are based
569 * on coincident nodes (with a specified precision).
570 * \param [in] other - the mesh to compare with.
571 * \param [in] prec - the precision used to compare nodes of the two meshes.
572 * \throw If the two meshes do not match.
574 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
576 MEDCouplingPointSet::checkFastEquivalWith(other,prec);
577 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
579 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !");
583 * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
584 * cells each node belongs to.
585 * \warning For speed reasons, this method does not check if node ids in the nodal
586 * connectivity correspond to the size of node coordinates array.
587 * \param [in,out] revNodal - an array holding ids of cells sharing each node.
588 * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
589 * dividing cell ids in \a revNodal into groups each referring to one
590 * node. Its every element (except the last one) is an index pointing to the
591 * first id of a group of cells. For example cells sharing the node #1 are
592 * described by following range of indices:
593 * [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
594 * \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
595 * Number of cells sharing the *i*-th node is
596 * \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
597 * \throw If the coordinates array is not set.
598 * \throw If the nodal connectivity of cells is not defined.
600 * \if ENABLE_EXAMPLES
601 * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
602 * \ref py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
605 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
608 int nbOfNodes=getNumberOfNodes();
609 int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
610 revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
611 std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
612 const int *conn=_nodal_connec->getConstPointer();
613 const int *connIndex=_nodal_connec_index->getConstPointer();
614 int nbOfCells=getNumberOfCells();
615 int nbOfEltsInRevNodal=0;
616 for(int eltId=0;eltId<nbOfCells;eltId++)
618 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
619 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
620 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
621 if(*iter>=0)//for polyhedrons
623 nbOfEltsInRevNodal++;
624 revNodalIndxPtr[(*iter)+1]++;
627 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
628 int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
629 revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
630 std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
631 for(int eltId=0;eltId<nbOfCells;eltId++)
633 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
634 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
635 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
636 if(*iter>=0)//for polyhedrons
637 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
643 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
648 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
654 if(cm.getOrientationStatus(nb,conn1,conn2))
661 class MinusOneSonsGenerator
664 MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
665 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
666 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
667 static const int DELTA=1;
669 const INTERP_KERNEL::CellModel& _cm;
672 class MinusOneSonsGeneratorBiQuadratic
675 MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
676 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
677 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
678 static const int DELTA=1;
680 const INTERP_KERNEL::CellModel& _cm;
683 class MinusTwoSonsGenerator
686 MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
687 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
688 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
689 static const int DELTA=2;
691 const INTERP_KERNEL::CellModel& _cm;
697 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
698 * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
699 * describing correspondence between cells of \a this and the result meshes are
700 * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
701 * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
702 * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
703 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
704 * \warning For speed reasons, this method does not check if node ids in the nodal
705 * connectivity correspond to the size of node coordinates array.
706 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
707 * to write this mesh to the MED file, its cells must be sorted using
708 * sortCellsInMEDFileFrmt().
709 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
710 * each cell of \a this mesh.
711 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
712 * dividing cell ids in \a desc into groups each referring to one
713 * cell of \a this mesh. Its every element (except the last one) is an index
714 * pointing to the first id of a group of cells. For example cells of the
715 * result mesh bounding the cell #1 of \a this mesh are described by following
717 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
718 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
719 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
720 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
721 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
722 * by each cell of the result mesh.
723 * \param [in,out] revDescIndx - the array, of length one more than number of cells
724 * in the result mesh,
725 * dividing cell ids in \a revDesc into groups each referring to one
726 * cell of the result mesh the same way as \a descIndx divides \a desc.
727 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
728 * delete this mesh using decrRef() as it is no more needed.
729 * \throw If the coordinates array is not set.
730 * \throw If the nodal connectivity of cells is node defined.
731 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
732 * revDescIndx == NULL.
734 * \if ENABLE_EXAMPLES
735 * \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
736 * \ref py_mcumesh_buildDescendingConnectivity "Here is a Python example".
738 * \sa buildDescendingConnectivity2()
740 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
742 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
746 * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
747 * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
748 * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
749 * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
750 * \sa MEDCouplingUMesh::buildDescendingConnectivity
752 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
755 if(getMeshDimension()!=3)
756 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
757 return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
761 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
762 * this->getMeshDimension(), that bound cells of \a this mesh. In
763 * addition arrays describing correspondence between cells of \a this and the result
764 * meshes are returned. The arrays \a desc and \a descIndx describe the descending
765 * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
766 * mesh. This method differs from buildDescendingConnectivity() in that apart
767 * from cell ids, \a desc returns mutual orientation of cells in \a this and the
768 * result meshes. So a positive id means that order of nodes in corresponding cells
769 * of two meshes is same, and a negative id means a reverse order of nodes. Since a
770 * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
771 * i.e. cell ids are one-based.
772 * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
773 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
774 * \warning For speed reasons, this method does not check if node ids in the nodal
775 * connectivity correspond to the size of node coordinates array.
776 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
777 * to write this mesh to the MED file, its cells must be sorted using
778 * sortCellsInMEDFileFrmt().
779 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
780 * each cell of \a this mesh.
781 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
782 * dividing cell ids in \a desc into groups each referring to one
783 * cell of \a this mesh. Its every element (except the last one) is an index
784 * pointing to the first id of a group of cells. For example cells of the
785 * result mesh bounding the cell #1 of \a this mesh are described by following
787 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
788 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
789 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
790 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
791 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
792 * by each cell of the result mesh.
793 * \param [in,out] revDescIndx - the array, of length one more than number of cells
794 * in the result mesh,
795 * dividing cell ids in \a revDesc into groups each referring to one
796 * cell of the result mesh the same way as \a descIndx divides \a desc.
797 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
798 * shares the node coordinates array with \a this mesh. The caller is to
799 * delete this mesh using decrRef() as it is no more needed.
800 * \throw If the coordinates array is not set.
801 * \throw If the nodal connectivity of cells is node defined.
802 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
803 * revDescIndx == NULL.
805 * \if ENABLE_EXAMPLES
806 * \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
807 * \ref py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
809 * \sa buildDescendingConnectivity()
811 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
813 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
817 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
818 * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
819 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
820 * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
822 * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
823 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
824 * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
826 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
828 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
829 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
830 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
831 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
832 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
834 ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
838 * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
839 * This method is useful for users that want to reduce along a criterion the set of neighbours cell. This is typically the case to extract a set a neighbours,
840 * excluding a set of meshdim-1 cells in input descending connectivity.
841 * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
842 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
843 * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
845 * \param [in] desc descending connectivity array.
846 * \param [in] descIndx descending connectivity index array used to walk through \b desc.
847 * \param [in] revDesc reverse descending connectivity array.
848 * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
849 * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
850 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
851 * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
853 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
854 DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx)
856 if(!desc || !descIndx || !revDesc || !revDescIndx)
857 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
858 const int *descPtr=desc->getConstPointer();
859 const int *descIPtr=descIndx->getConstPointer();
860 const int *revDescPtr=revDesc->getConstPointer();
861 const int *revDescIPtr=revDescIndx->getConstPointer();
863 int nbCells=descIndx->getNumberOfTuples()-1;
864 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
865 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
866 int *out1Ptr=out1->getPointer();
868 out0->reserve(desc->getNumberOfTuples());
869 for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
871 for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
873 std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
875 out0->insertAtTheEnd(s.begin(),s.end());
877 *out1Ptr=out0->getNumberOfTuples();
879 neighbors=out0.retn();
880 neighborsIndx=out1.retn();
884 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
885 * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
886 * This method lists node by node in \b this which are its neighbors. To compute the result only connectivities are considered.
887 * The neighbor nodes of node having id 'nodeId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
889 * \param [out] neighbors is an array storing all the neighbors of all nodes in \b this. This array is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
890 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
891 * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
893 void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayInt *&neighbors, DataArrayInt *&neighborsIdx) const
896 int mdim(getMeshDimension()),nbNodes(getNumberOfNodes());
897 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descIndx(DataArrayInt::New()),revDesc(DataArrayInt::New()),revDescIndx(DataArrayInt::New());
898 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh1D;
903 mesh1D=explode3DMeshTo1D(desc,descIndx,revDesc,revDescIndx);
908 mesh1D=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
913 mesh1D=const_cast<MEDCouplingUMesh *>(this);
919 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2,1] !");
922 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=0; revDescIndx=0;
923 mesh1D->getReverseNodalConnectivity(desc,descIndx);
924 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0(DataArrayInt::New());
925 ret0->alloc(desc->getNumberOfTuples(),1);
926 int *r0Pt(ret0->getPointer());
927 const int *c1DPtr(mesh1D->getNodalConnectivity()->begin()),*rn(desc->begin()),*rni(descIndx->begin());
928 for(int i=0;i<nbNodes;i++,rni++)
930 for(const int *oneDCellIt=rn+rni[0];oneDCellIt!=rn+rni[1];oneDCellIt++)
931 *r0Pt++=c1DPtr[3*(*oneDCellIt)+1]==i?c1DPtr[3*(*oneDCellIt)+2]:c1DPtr[3*(*oneDCellIt)+1];
933 neighbors=ret0.retn();
934 neighborsIdx=descIndx.retn();
940 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
941 * For speed reasons no check of this will be done.
943 template<class SonsGenerator>
944 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
946 if(!desc || !descIndx || !revDesc || !revDescIndx)
947 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
948 checkConnectivityFullyDefined();
949 int nbOfCells=getNumberOfCells();
950 int nbOfNodes=getNumberOfNodes();
951 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
952 int *revNodalIndxPtr=revNodalIndx->getPointer();
953 const int *conn=_nodal_connec->getConstPointer();
954 const int *connIndex=_nodal_connec_index->getConstPointer();
955 std::string name="Mesh constituent of "; name+=getName();
956 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA);
957 ret->setCoords(getCoords());
958 ret->allocateCells(2*nbOfCells);
959 descIndx->alloc(nbOfCells+1,1);
960 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
961 int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
962 for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
964 int pos=connIndex[eltId];
965 int posP1=connIndex[eltId+1];
966 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
967 SonsGenerator sg(cm);
968 unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
969 INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
970 for(unsigned i=0;i<nbOfSons;i++)
972 INTERP_KERNEL::NormalizedCellType cmsId;
973 unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
974 for(unsigned k=0;k<nbOfNodesSon;k++)
976 revNodalIndxPtr[tmp[k]+1]++;
977 ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
978 revDesc2->pushBackSilent(eltId);
980 descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
982 int nbOfCellsM1=ret->getNumberOfCells();
983 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
984 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
985 std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
986 int *revNodalPtr=revNodal->getPointer();
987 const int *connM1=ret->getNodalConnectivity()->getConstPointer();
988 const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
989 for(int eltId=0;eltId<nbOfCellsM1;eltId++)
991 const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
992 const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
993 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
994 if(*iter>=0)//for polyhedrons
995 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
998 DataArrayInt *commonCells=0,*commonCellsI=0;
999 FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
1000 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1001 const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
1002 int newNbOfCellsM1=-1;
1003 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
1004 commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
1005 std::vector<bool> isImpacted(nbOfCellsM1,false);
1006 for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
1007 for(int work2=work[0];work2!=work[1];work2++)
1008 isImpacted[commonCellsPtr[work2]]=true;
1009 const int *o2nM1Ptr=o2nM1->getConstPointer();
1010 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
1011 const int *n2oM1Ptr=n2oM1->getConstPointer();
1012 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
1013 ret2->copyTinyInfoFrom(this);
1014 desc->alloc(descIndx->back(),1);
1015 int *descPtr=desc->getPointer();
1016 const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
1017 for(int i=0;i<nbOfCellsM1;i++,descPtr++)
1020 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1023 if(i!=n2oM1Ptr[o2nM1Ptr[i]])
1025 const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
1026 *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
1029 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1032 revDesc->reserve(newNbOfCellsM1);
1033 revDescIndx->alloc(newNbOfCellsM1+1,1);
1034 int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
1035 const int *revDesc2Ptr=revDesc2->getConstPointer();
1036 for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
1038 int oldCellIdM1=n2oM1Ptr[i];
1039 if(!isImpacted[oldCellIdM1])
1041 revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
1042 revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
1046 for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
1047 revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
1048 revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
1056 struct MEDCouplingAccVisit
1058 MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1059 int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1060 int _new_nb_of_nodes;
1066 * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1067 * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1068 * array of cell ids. Pay attention that after conversion all algorithms work slower
1069 * with \a this mesh than before conversion. <br> If an exception is thrown during the
1070 * conversion due presence of invalid ids in the array of cells to convert, as a
1071 * result \a this mesh contains some already converted elements. In this case the 2D
1072 * mesh remains valid but 3D mesh becomes \b inconsistent!
1073 * \warning This method can significantly modify the order of geometric types in \a this,
1074 * hence, to write this mesh to the MED file, its cells must be sorted using
1075 * sortCellsInMEDFileFrmt().
1076 * \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1077 * \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1078 * cellIdsToConvertBg.
1079 * \throw If the coordinates array is not set.
1080 * \throw If the nodal connectivity of cells is node defined.
1081 * \throw If dimension of \a this mesh is not either 2 or 3.
1083 * \if ENABLE_EXAMPLES
1084 * \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1085 * \ref py_mcumesh_convertToPolyTypes "Here is a Python example".
1088 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1090 checkFullyDefined();
1091 int dim=getMeshDimension();
1093 throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1094 int nbOfCells(getNumberOfCells());
1097 const int *connIndex=_nodal_connec_index->getConstPointer();
1098 int *conn=_nodal_connec->getPointer();
1099 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1101 if(*iter>=0 && *iter<nbOfCells)
1103 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1104 if(!cm.isQuadratic())
1105 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1107 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1111 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1112 oss << " in range [0," << nbOfCells << ") !";
1113 throw INTERP_KERNEL::Exception(oss.str().c_str());
1119 int *connIndex(_nodal_connec_index->getPointer());
1120 const int *connOld(_nodal_connec->getConstPointer());
1121 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1122 std::vector<bool> toBeDone(nbOfCells,false);
1123 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1125 if(*iter>=0 && *iter<nbOfCells)
1126 toBeDone[*iter]=true;
1129 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1130 oss << " in range [0," << nbOfCells << ") !";
1131 throw INTERP_KERNEL::Exception(oss.str().c_str());
1134 for(int cellId=0;cellId<nbOfCells;cellId++)
1136 int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1137 int lgthOld(posP1-pos-1);
1138 if(toBeDone[cellId])
1140 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1141 unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1142 int *tmp(new int[nbOfFaces*lgthOld+1]);
1143 int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1144 for(unsigned j=0;j<nbOfFaces;j++)
1146 INTERP_KERNEL::NormalizedCellType type;
1147 unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1151 std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1152 connNew->pushBackValsSilent(tmp,tmp+newLgth);
1153 connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1158 connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1159 connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1162 setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1168 * Converts all cells to either polygons (if \a this is a 2D mesh) or
1169 * polyhedrons (if \a this is a 3D mesh).
1170 * \warning As this method is purely for user-friendliness and no optimization is
1171 * done to avoid construction of a useless vector, this method can be costly
1173 * \throw If the coordinates array is not set.
1174 * \throw If the nodal connectivity of cells is node defined.
1175 * \throw If dimension of \a this mesh is not either 2 or 3.
1177 void MEDCouplingUMesh::convertAllToPoly()
1179 int nbOfCells=getNumberOfCells();
1180 std::vector<int> cellIds(nbOfCells);
1181 for(int i=0;i<nbOfCells;i++)
1183 convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1187 * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1188 * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1189 * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1190 * base facet of the volume and the second half of nodes describes an opposite facet
1191 * having the same number of nodes as the base one. This method converts such
1192 * connectivity to a valid polyhedral format where connectivity of each facet is
1193 * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1194 * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1195 * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1196 * a correct orientation of the first facet of a polyhedron, else orientation of a
1197 * corrected cell is reverse.<br>
1198 * This method is useful to build an extruded unstructured mesh with polyhedrons as
1199 * it releases the user from boring description of polyhedra connectivity in the valid
1201 * \throw If \a this->getMeshDimension() != 3.
1202 * \throw If \a this->getSpaceDimension() != 3.
1203 * \throw If the nodal connectivity of cells is not defined.
1204 * \throw If the coordinates array is not set.
1205 * \throw If \a this mesh contains polyhedrons with the valid connectivity.
1206 * \throw If \a this mesh contains polyhedrons with odd number of nodes.
1208 * \if ENABLE_EXAMPLES
1209 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1210 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1213 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1215 checkFullyDefined();
1216 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1217 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1218 int nbOfCells=getNumberOfCells();
1219 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1220 newCi->alloc(nbOfCells+1,1);
1221 int *newci=newCi->getPointer();
1222 const int *ci=_nodal_connec_index->getConstPointer();
1223 const int *c=_nodal_connec->getConstPointer();
1225 for(int i=0;i<nbOfCells;i++)
1227 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1228 if(type==INTERP_KERNEL::NORM_POLYHED)
1230 if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1232 std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1233 throw INTERP_KERNEL::Exception(oss.str().c_str());
1235 std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1238 std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron with 1 face but there is a mismatch of number of nodes in face should be even !";
1239 throw INTERP_KERNEL::Exception(oss.str().c_str());
1242 newci[i+1]=7*n1+2+newci[i];//6*n1 (nodal length) + n1+2 (number of faces) - 1 (number of '-1' separator is equal to number of faces -1) + 1 (for cell type)
1245 newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1247 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1248 newC->alloc(newci[nbOfCells],1);
1249 int *newc=newC->getPointer();
1250 for(int i=0;i<nbOfCells;i++)
1252 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1253 if(type==INTERP_KERNEL::NORM_POLYHED)
1255 std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1256 newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1258 for(std::size_t j=0;j<n1;j++)
1260 newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1262 newc[n1+5*j+1]=c[ci[i]+1+j];
1263 newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1264 newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1265 newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1270 newc=std::copy(c+ci[i],c+ci[i+1],newc);
1272 _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1273 _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1278 * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1279 * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1280 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1281 * to write this mesh to the MED file, its cells must be sorted using
1282 * sortCellsInMEDFileFrmt().
1283 * \return \c true if at least one cell has been converted, \c false else. In the
1284 * last case the nodal connectivity remains unchanged.
1285 * \throw If the coordinates array is not set.
1286 * \throw If the nodal connectivity of cells is not defined.
1287 * \throw If \a this->getMeshDimension() < 0.
1289 bool MEDCouplingUMesh::unPolyze()
1291 checkFullyDefined();
1292 int mdim=getMeshDimension();
1294 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1297 int nbOfCells=getNumberOfCells();
1300 int initMeshLgth=getMeshLength();
1301 int *conn=_nodal_connec->getPointer();
1302 int *index=_nodal_connec_index->getPointer();
1307 for(int i=0;i<nbOfCells;i++)
1309 lgthOfCurCell=index[i+1]-posOfCurCell;
1310 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1311 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1312 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1316 switch(cm.getDimension())
1320 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1321 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1322 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1327 int nbOfFaces,lgthOfPolyhConn;
1328 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1329 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1334 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1338 ret=ret || (newType!=type);
1339 conn[newPos]=newType;
1341 posOfCurCell=index[i+1];
1346 std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1347 newPos+=lgthOfCurCell;
1348 posOfCurCell+=lgthOfCurCell;
1352 if(newPos!=initMeshLgth)
1353 _nodal_connec->reAlloc(newPos);
1360 * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1361 * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1362 * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells.
1364 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not. This epsilon is used to recenter around origin to have maximal
1367 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1369 checkFullyDefined();
1370 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1371 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1372 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1373 coords->recenterForMaxPrecision(eps);
1375 int nbOfCells=getNumberOfCells();
1376 const int *conn=_nodal_connec->getConstPointer();
1377 const int *index=_nodal_connec_index->getConstPointer();
1378 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1379 connINew->alloc(nbOfCells+1,1);
1380 int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1381 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1383 for(int i=0;i<nbOfCells;i++,connINewPtr++)
1385 if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1387 SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1391 connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1392 *connINewPtr=connNew->getNumberOfTuples();
1395 setConnectivity(connNew,connINew,false);
1399 * This method returns all node ids used in the connectivity of \b this. The data array returned has to be dealt by the caller.
1400 * The returned node ids are sorted ascendingly. This method is close to MEDCouplingUMesh::getNodeIdsInUse except
1401 * the format of the 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 finds in \b this the cell 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 cell ids set in \b this lying on at least one node in the fetched nodes in \b otherDimM1OnSameCoords.
2334 * This method returns the 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 the cell ids of s0 (which are cell ids of \b this) in the above algorithm.
2343 * \param [out] cellIdsRk1 a newly allocated array containing the cell ids of s1+s2 \b into the \b cellIdsRk0 subset. To get the 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 int nCells2 = m0Part2->getNumberOfCells();
2470 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2471 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2472 // Neighbor information of the mesh without considering the crack (serves to count how many connex pieces it is made of)
2473 DataArrayInt *tmp00=0,*tmp11=0;
2474 MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00, tmp00, tmp11);
2475 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighInit00(tmp00);
2476 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighIInit00(tmp11);
2477 // Neighbor information of the mesh WITH the crack (some neighbors are removed):
2478 DataArrayInt *idsTmp=0;
2479 bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2480 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2482 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2483 // In the neighbor information remove the connection between high dimension cells and its low level constituents which are part
2484 // of the frontier given in parameter (i.e. the cells of low dimension from the group delimiting the crack):
2485 MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2486 DataArrayInt *tmp0=0,*tmp1=0;
2487 // Compute the neighbor of each cell in m0Part2, taking into account the broken link above. Two
2488 // cells on either side of the crack (defined by the mesh of low dimension) are not neighbor anymore.
2489 ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2490 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2491 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2494 // For each initial connex part of the sub-mesh (or said differently for each independent crack):
2495 int seed = 0, nIter = 0;
2496 int nIterMax = nCells2+1; // Safety net for the loop
2497 bool * hitCells = new bool[nCells2];
2498 for (int iii=0; iii<nCells2; iii++) hitCells[iii] = false;
2499 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum = DataArrayInt::New();
2500 cellsToModifyConn0_torenum->alloc(0,1);
2501 while (nIter < nIterMax)
2503 if (std::find(hitCells, hitCells+nCells2, false) == hitCells+nCells2)
2505 // Connex zone without the crack (to compute the next seed really)
2507 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connexCheck = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neighInit00,neighIInit00, -1, dnu);
2509 for (int * ptr = connexCheck->getPointer(); cnt < connexCheck->getNumberOfTuples(); ptr++, cnt++)
2510 hitCells[*ptr] = true;
2511 // Connex zone WITH the crack (to identify cells lying on either part of the crack)
2512 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> spreadZone = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neigh00,neighI00, -1, dnu);
2513 cellsToModifyConn0_torenum = DataArrayInt::Aggregate(cellsToModifyConn0_torenum, spreadZone, 0);
2514 // Compute next seed, i.e. a cell in another connex part:
2515 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comple = cellsToModifyConn0_torenum->buildComplement(nCells2);
2516 seed = comple->getIJ(0,0);
2520 if (nIter >= nIterMax)
2521 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate(): internal error - too many iterations.");
2523 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2524 cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2525 cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2527 cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2528 cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2529 nodeIdsToDuplicate=s3.retn();
2533 * This method operates a modification of the connectivity and coords in \b this.
2534 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2535 * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2536 * 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
2537 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2538 * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2540 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2542 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2543 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2545 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2547 int nbOfNodes=getNumberOfNodes();
2548 duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2549 duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2553 * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of
2554 * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range !
2556 * \param [in] offset - specifies the offset to be applied on each element of connectivity.
2558 * \sa renumberNodesInConn
2560 void MEDCouplingUMesh::renumberNodesWithOffsetInConn(int offset)
2562 checkConnectivityFullyDefined();
2563 int *conn(getNodalConnectivity()->getPointer());
2564 const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2565 int nbOfCells(getNumberOfCells());
2566 for(int i=0;i<nbOfCells;i++)
2567 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2569 int& node=conn[iconn];
2570 if(node>=0)//avoid polyhedron separator
2575 _nodal_connec->declareAsNew();
2580 * Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
2581 * 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
2584 void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& newNodeNumbersO2N)
2586 checkConnectivityFullyDefined();
2587 int *conn(getNodalConnectivity()->getPointer());
2588 const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2589 int nbOfCells(getNumberOfCells());
2590 for(int i=0;i<nbOfCells;i++)
2591 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2593 int& node=conn[iconn];
2594 if(node>=0)//avoid polyhedron separator
2596 INTERP_KERNEL::HashMap<int,int>::const_iterator it(newNodeNumbersO2N.find(node));
2597 if(it!=newNodeNumbersO2N.end())
2603 std::ostringstream oss; oss << "MEDCouplingUMesh::renumberNodesInConn(map) : presence in connectivity for cell #" << i << " of node #" << node << " : Not in map !";
2604 throw INTERP_KERNEL::Exception(oss.str().c_str());
2608 _nodal_connec->declareAsNew();
2613 * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2614 * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2615 * This method is a generalization of shiftNodeNumbersInConn().
2616 * \warning This method performs no check of validity of new ids. **Use it with care !**
2617 * \param [in] newNodeNumbersO2N - a permutation array, of length \a
2618 * this->getNumberOfNodes(), in "Old to New" mode.
2619 * See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2620 * \throw If the nodal connectivity of cells is not defined.
2622 * \if ENABLE_EXAMPLES
2623 * \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2624 * \ref py_mcumesh_renumberNodesInConn "Here is a Python example".
2627 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2629 checkConnectivityFullyDefined();
2630 int *conn=getNodalConnectivity()->getPointer();
2631 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2632 int nbOfCells(getNumberOfCells());
2633 for(int i=0;i<nbOfCells;i++)
2634 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2636 int& node=conn[iconn];
2637 if(node>=0)//avoid polyhedron separator
2639 node=newNodeNumbersO2N[node];
2642 _nodal_connec->declareAsNew();
2647 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2648 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2649 * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2651 * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2653 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2655 checkConnectivityFullyDefined();
2656 int *conn=getNodalConnectivity()->getPointer();
2657 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2658 int nbOfCells=getNumberOfCells();
2659 for(int i=0;i<nbOfCells;i++)
2660 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2662 int& node=conn[iconn];
2663 if(node>=0)//avoid polyhedron separator
2668 _nodal_connec->declareAsNew();
2673 * This method operates a modification of the connectivity in \b this.
2674 * 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.
2675 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2676 * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2677 * 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
2678 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2679 * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2681 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2682 * As an another consequense after the call of this method \b this can be transiently non cohrent.
2684 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2685 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2686 * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ).
2688 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2690 checkConnectivityFullyDefined();
2691 std::map<int,int> m;
2693 for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2695 int *conn=getNodalConnectivity()->getPointer();
2696 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2697 int nbOfCells=getNumberOfCells();
2698 for(int i=0;i<nbOfCells;i++)
2699 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2701 int& node=conn[iconn];
2702 if(node>=0)//avoid polyhedron separator
2704 std::map<int,int>::iterator it=m.find(node);
2713 * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2715 * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2716 * After the call of this method the number of cells remains the same as before.
2718 * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2719 * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2720 * be strictly in [0;this->getNumberOfCells()).
2722 * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2723 * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2724 * should be contained in[0;this->getNumberOfCells()).
2726 * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2728 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2730 checkConnectivityFullyDefined();
2731 int nbCells=getNumberOfCells();
2732 const int *array=old2NewBg;
2734 array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2736 const int *conn=_nodal_connec->getConstPointer();
2737 const int *connI=_nodal_connec_index->getConstPointer();
2738 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2739 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2740 const int *n2oPtr=n2o->begin();
2741 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2742 newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2743 newConn->copyStringInfoFrom(*_nodal_connec);
2744 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2745 newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2746 newConnI->copyStringInfoFrom(*_nodal_connec_index);
2748 int *newC=newConn->getPointer();
2749 int *newCI=newConnI->getPointer();
2752 for(int i=0;i<nbCells;i++)
2755 int nbOfElts=connI[pos+1]-connI[pos];
2756 newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2761 setConnectivity(newConn,newConnI);
2763 free(const_cast<int *>(array));
2767 * Finds cells whose bounding boxes intersect a given bounding box.
2768 * \param [in] bbox - an array defining the bounding box via coordinates of its
2769 * extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2771 * \param [in] eps - a factor used to increase size of the bounding box of cell
2772 * before comparing it with \a bbox. This factor is multiplied by the maximal
2773 * extent of the bounding box of cell to produce an addition to this bounding box.
2774 * \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2775 * cells. The caller is to delete this array using decrRef() as it is no more
2777 * \throw If the coordinates array is not set.
2778 * \throw If the nodal connectivity of cells is not defined.
2780 * \if ENABLE_EXAMPLES
2781 * \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2782 * \ref py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2785 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2787 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2788 if(getMeshDimension()==-1)
2790 elems->pushBackSilent(0);
2791 return elems.retn();
2793 int dim=getSpaceDimension();
2794 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2795 const int* conn = getNodalConnectivity()->getConstPointer();
2796 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2797 const double* coords = getCoords()->getConstPointer();
2798 int nbOfCells=getNumberOfCells();
2799 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2801 for (int i=0; i<dim; i++)
2803 elem_bb[i*2]=std::numeric_limits<double>::max();
2804 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2807 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2809 int node= conn[inode];
2810 if(node>=0)//avoid polyhedron separator
2812 for (int idim=0; idim<dim; idim++)
2814 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2816 elem_bb[idim*2] = coords[node*dim+idim] ;
2818 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2820 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2825 if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2826 elems->pushBackSilent(ielem);
2828 return elems.retn();
2832 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2833 * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2834 * added in 'elems' parameter.
2836 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2838 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2839 if(getMeshDimension()==-1)
2841 elems->pushBackSilent(0);
2842 return elems.retn();
2844 int dim=getSpaceDimension();
2845 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2846 const int* conn = getNodalConnectivity()->getConstPointer();
2847 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2848 const double* coords = getCoords()->getConstPointer();
2849 int nbOfCells=getNumberOfCells();
2850 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2852 for (int i=0; i<dim; i++)
2854 elem_bb[i*2]=std::numeric_limits<double>::max();
2855 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2858 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2860 int node= conn[inode];
2861 if(node>=0)//avoid polyhedron separator
2863 for (int idim=0; idim<dim; idim++)
2865 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2867 elem_bb[idim*2] = coords[node*dim+idim] ;
2869 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2871 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2876 if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2877 elems->pushBackSilent(ielem);
2879 return elems.retn();
2883 * Returns a type of a cell by its id.
2884 * \param [in] cellId - the id of the cell of interest.
2885 * \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2886 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2888 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2890 const int *ptI=_nodal_connec_index->getConstPointer();
2891 const int *pt=_nodal_connec->getConstPointer();
2892 if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2893 return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2896 std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2897 throw INTERP_KERNEL::Exception(oss.str().c_str());
2902 * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2903 * This method does not throw exception if geometric type \a type is not in \a this.
2904 * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2905 * The coordinates array is not considered here.
2907 * \param [in] type the geometric type
2908 * \return cell ids in this having geometric type \a type.
2910 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2913 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2915 checkConnectivityFullyDefined();
2916 int nbCells=getNumberOfCells();
2917 int mdim=getMeshDimension();
2918 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2919 if(mdim!=(int)cm.getDimension())
2920 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2921 const int *ptI=_nodal_connec_index->getConstPointer();
2922 const int *pt=_nodal_connec->getConstPointer();
2923 for(int i=0;i<nbCells;i++)
2925 if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2926 ret->pushBackSilent(i);
2932 * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2934 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2936 const int *ptI=_nodal_connec_index->getConstPointer();
2937 const int *pt=_nodal_connec->getConstPointer();
2938 int nbOfCells=getNumberOfCells();
2940 for(int i=0;i<nbOfCells;i++)
2941 if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2947 * Returns the nodal connectivity of a given cell.
2948 * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2949 * all returned node ids can be used in getCoordinatesOfNode().
2950 * \param [in] cellId - an id of the cell of interest.
2951 * \param [in,out] conn - a vector where the node ids are appended. It is not
2952 * cleared before the appending.
2953 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2955 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2957 const int *ptI=_nodal_connec_index->getConstPointer();
2958 const int *pt=_nodal_connec->getConstPointer();
2959 for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2964 std::string MEDCouplingUMesh::simpleRepr() const
2966 static const char msg0[]="No coordinates specified !";
2967 std::ostringstream ret;
2968 ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2969 ret << "Description of mesh : \"" << getDescription() << "\"\n";
2971 double tt=getTime(tmpp1,tmpp2);
2972 ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2973 ret << "Iteration : " << tmpp1 << " Order : " << tmpp2 << "\n";
2975 { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2977 { ret << " Mesh dimension has not been set or is invalid !"; }
2980 const int spaceDim=getSpaceDimension();
2981 ret << spaceDim << "\nInfo attached on space dimension : ";
2982 for(int i=0;i<spaceDim;i++)
2983 ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2987 ret << msg0 << "\n";
2988 ret << "Number of nodes : ";
2990 ret << getNumberOfNodes() << "\n";
2992 ret << msg0 << "\n";
2993 ret << "Number of cells : ";
2994 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2995 ret << getNumberOfCells() << "\n";
2997 ret << "No connectivity specified !" << "\n";
2998 ret << "Cell types present : ";
2999 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
3001 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
3002 ret << cm.getRepr() << " ";
3008 std::string MEDCouplingUMesh::advancedRepr() const
3010 std::ostringstream ret;
3011 ret << simpleRepr();
3012 ret << "\nCoordinates array : \n___________________\n\n";
3014 _coords->reprWithoutNameStream(ret);
3016 ret << "No array set !\n";
3017 ret << "\n\nConnectivity arrays : \n_____________________\n\n";
3018 reprConnectivityOfThisLL(ret);
3023 * This method returns a C++ code that is a dump of \a this.
3024 * This method will throw if this is not fully defined.
3026 std::string MEDCouplingUMesh::cppRepr() const
3028 static const char coordsName[]="coords";
3029 static const char connName[]="conn";
3030 static const char connIName[]="connI";
3031 checkFullyDefined();
3032 std::ostringstream ret; ret << "// coordinates" << std::endl;
3033 _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
3034 _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
3035 _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
3036 ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
3037 ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
3038 ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
3039 ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
3043 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
3045 std::ostringstream ret;
3046 reprConnectivityOfThisLL(ret);
3051 * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
3052 * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
3053 * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
3056 * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
3057 * 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
3058 * with number of tuples set to 0, if not the array is taken as this in the returned instance.
3060 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
3062 int mdim=getMeshDimension();
3064 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
3065 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
3066 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
3067 bool needToCpyCT=true;
3070 tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
3078 if(!_nodal_connec_index)
3080 tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
3085 tmp2=_nodal_connec_index;
3088 ret->setConnectivity(tmp1,tmp2,false);
3093 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
3094 ret->setCoords(coords);
3097 ret->setCoords(_coords);
3101 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
3103 if(_nodal_connec!=0 && _nodal_connec_index!=0)
3105 int nbOfCells=getNumberOfCells();
3106 const int *c=_nodal_connec->getConstPointer();
3107 const int *ci=_nodal_connec_index->getConstPointer();
3108 for(int i=0;i<nbOfCells;i++)
3110 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3111 stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3112 std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3117 stream << "Connectivity not defined !\n";
3120 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3122 const int *ptI=_nodal_connec_index->getConstPointer();
3123 const int *pt=_nodal_connec->getConstPointer();
3124 if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3125 return ptI[cellId+1]-ptI[cellId]-1;
3127 return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3131 * Returns types of cells of the specified part of \a this mesh.
3132 * This method avoids computing sub-mesh explicitely to get its types.
3133 * \param [in] begin - an array of cell ids of interest.
3134 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3135 * \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3136 * describing the cell types.
3137 * \throw If the coordinates array is not set.
3138 * \throw If the nodal connectivity of cells is not defined.
3139 * \sa getAllGeoTypes()
3141 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3143 checkFullyDefined();
3144 std::set<INTERP_KERNEL::NormalizedCellType> ret;
3145 const int *conn=_nodal_connec->getConstPointer();
3146 const int *connIndex=_nodal_connec_index->getConstPointer();
3147 for(const int *w=begin;w!=end;w++)
3148 ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3153 * Defines the nodal connectivity using given connectivity arrays. Optionally updates
3154 * a set of types of cells constituting \a this mesh.
3155 * This method is for advanced users having prepared their connectivity before. For
3156 * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3157 * \param [in] conn - the nodal connectivity array.
3158 * \param [in] connIndex - the nodal connectivity index array.
3159 * \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3162 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3164 DataArrayInt::SetArrayIn(conn,_nodal_connec);
3165 DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3166 if(isComputingTypes)
3172 * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
3173 * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3175 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3176 _nodal_connec(0),_nodal_connec_index(0),
3177 _types(other._types)
3179 if(other._nodal_connec)
3180 _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3181 if(other._nodal_connec_index)
3182 _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3185 MEDCouplingUMesh::~MEDCouplingUMesh()
3188 _nodal_connec->decrRef();
3189 if(_nodal_connec_index)
3190 _nodal_connec_index->decrRef();
3194 * Recomputes a set of cell types of \a this mesh. For more info see
3195 * \ref MEDCouplingUMeshNodalConnectivity.
3197 void MEDCouplingUMesh::computeTypes()
3199 ComputeAllTypesInternal(_types,_nodal_connec,_nodal_connec_index);
3203 * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3205 void MEDCouplingUMesh::checkFullyDefined() const
3207 if(!_nodal_connec_index || !_nodal_connec || !_coords)
3208 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3212 * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3214 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3216 if(!_nodal_connec_index || !_nodal_connec)
3217 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3221 * Returns a number of cells constituting \a this mesh.
3222 * \return int - the number of cells in \a this mesh.
3223 * \throw If the nodal connectivity of cells is not defined.
3225 int MEDCouplingUMesh::getNumberOfCells() const
3227 if(_nodal_connec_index)
3228 return _nodal_connec_index->getNumberOfTuples()-1;
3233 throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3237 * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3238 * mesh. For more info see \ref MEDCouplingMeshesPage.
3239 * \return int - the dimension of \a this mesh.
3240 * \throw If the mesh dimension is not defined using setMeshDimension().
3242 int MEDCouplingUMesh::getMeshDimension() const
3245 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3250 * Returns a length of the nodal connectivity array.
3251 * This method is for test reason. Normally the integer returned is not useable by
3252 * user. For more info see \ref MEDCouplingUMeshNodalConnectivity.
3253 * \return int - the length of the nodal connectivity array.
3255 int MEDCouplingUMesh::getMeshLength() const
3257 return _nodal_connec->getNbOfElems();
3261 * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3263 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3265 MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3266 tinyInfo.push_back(getMeshDimension());
3267 tinyInfo.push_back(getNumberOfCells());
3269 tinyInfo.push_back(getMeshLength());
3271 tinyInfo.push_back(-1);
3275 * First step of unserialization process.
3277 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3279 return tinyInfo[6]<=0;
3283 * Second step of serialization process.
3284 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3286 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3288 MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3290 a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3294 * Third and final step of serialization process.
3296 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3298 MEDCouplingPointSet::serialize(a1,a2);
3299 if(getMeshDimension()>-1)
3301 a1=DataArrayInt::New();
3302 a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3303 int *ptA1=a1->getPointer();
3304 const int *conn=getNodalConnectivity()->getConstPointer();
3305 const int *index=getNodalConnectivityIndex()->getConstPointer();
3306 ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3307 std::copy(conn,conn+getMeshLength(),ptA1);
3314 * Second and final unserialization process.
3315 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3317 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3319 MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3320 setMeshDimension(tinyInfo[5]);
3324 const int *recvBuffer=a1->getConstPointer();
3325 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3326 myConnecIndex->alloc(tinyInfo[6]+1,1);
3327 std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3328 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3329 myConnec->alloc(tinyInfo[7],1);
3330 std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3331 setConnectivity(myConnec, myConnecIndex);
3336 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3337 * CellIds are given using range specified by a start an end and step.
3339 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3341 checkFullyDefined();
3342 int ncell=getNumberOfCells();
3343 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3344 ret->_mesh_dim=_mesh_dim;
3345 ret->setCoords(_coords);
3346 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3347 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3348 int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3350 const int *conn=_nodal_connec->getConstPointer();
3351 const int *connIndex=_nodal_connec_index->getConstPointer();
3352 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3354 if(work>=0 && work<ncell)
3356 newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3360 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3361 throw INTERP_KERNEL::Exception(oss.str().c_str());
3364 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3365 int *newConnPtr=newConn->getPointer();
3366 std::set<INTERP_KERNEL::NormalizedCellType> types;
3368 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3370 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3371 newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3373 ret->setConnectivity(newConn,newConnI,false);
3375 ret->copyTinyInfoFrom(this);
3380 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3381 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3382 * The return newly allocated mesh will share the same coordinates as \a this.
3384 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3386 checkConnectivityFullyDefined();
3387 int ncell=getNumberOfCells();
3388 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3389 ret->_mesh_dim=_mesh_dim;
3390 ret->setCoords(_coords);
3391 std::size_t nbOfElemsRet=std::distance(begin,end);
3392 int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3394 const int *conn=_nodal_connec->getConstPointer();
3395 const int *connIndex=_nodal_connec_index->getConstPointer();
3397 for(const int *work=begin;work!=end;work++,newNbring++)
3399 if(*work>=0 && *work<ncell)
3400 connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3404 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3405 throw INTERP_KERNEL::Exception(oss.str().c_str());
3408 int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3409 int *connRetWork=connRet;
3410 std::set<INTERP_KERNEL::NormalizedCellType> types;
3411 for(const int *work=begin;work!=end;work++)
3413 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3414 connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3416 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3417 connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3418 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3419 connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3420 ret->setConnectivity(connRetArr,connIndexRetArr,false);
3422 ret->copyTinyInfoFrom(this);
3427 * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3429 * For 1D cells, the returned field contains lengths.<br>
3430 * For 2D cells, the returned field contains areas.<br>
3431 * For 3D cells, the returned field contains volumes.
3432 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3433 * orientation, i.e. the volume is always positive.
3434 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3435 * and one time . The caller is to delete this field using decrRef() as it is no
3438 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3440 std::string name="MeasureOfMesh_";
3442 int nbelem=getNumberOfCells();
3443 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3444 field->setName(name);
3445 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3446 array->alloc(nbelem,1);
3447 double *area_vol=array->getPointer();
3448 field->setArray(array) ; array=0;
3449 field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3450 field->synchronizeTimeWithMesh();
3451 if(getMeshDimension()!=-1)
3454 INTERP_KERNEL::NormalizedCellType type;
3455 int dim_space=getSpaceDimension();
3456 const double *coords=getCoords()->getConstPointer();
3457 const int *connec=getNodalConnectivity()->getConstPointer();
3458 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3459 for(int iel=0;iel<nbelem;iel++)
3461 ipt=connec_index[iel];
3462 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3463 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);
3466 std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3470 area_vol[0]=std::numeric_limits<double>::max();
3472 return field.retn();
3476 * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3478 * For 1D cells, the returned array contains lengths.<br>
3479 * For 2D cells, the returned array contains areas.<br>
3480 * For 3D cells, the returned array contains volumes.
3481 * This method avoids building explicitly a part of \a this mesh to perform the work.
3482 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3483 * orientation, i.e. the volume is always positive.
3484 * \param [in] begin - an array of cell ids of interest.
3485 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3486 * \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3487 * delete this array using decrRef() as it is no more needed.
3489 * \if ENABLE_EXAMPLES
3490 * \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3491 * \ref py_mcumesh_getPartMeasureField "Here is a Python example".
3493 * \sa getMeasureField()
3495 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3497 std::string name="PartMeasureOfMesh_";
3499 int nbelem=(int)std::distance(begin,end);
3500 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3501 array->setName(name);
3502 array->alloc(nbelem,1);
3503 double *area_vol=array->getPointer();
3504 if(getMeshDimension()!=-1)
3507 INTERP_KERNEL::NormalizedCellType type;
3508 int dim_space=getSpaceDimension();
3509 const double *coords=getCoords()->getConstPointer();
3510 const int *connec=getNodalConnectivity()->getConstPointer();
3511 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3512 for(const int *iel=begin;iel!=end;iel++)
3514 ipt=connec_index[*iel];
3515 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3516 *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3519 std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3523 area_vol[0]=std::numeric_limits<double>::max();
3525 return array.retn();
3529 * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3530 * \a this one. The returned field contains the dual cell volume for each corresponding
3531 * node in \a this mesh. In other words, the field returns the getMeasureField() of
3532 * the dual mesh in P1 sens of \a this.<br>
3533 * For 1D cells, the returned field contains lengths.<br>
3534 * For 2D cells, the returned field contains areas.<br>
3535 * For 3D cells, the returned field contains volumes.
3536 * This method is useful to check "P1*" conservative interpolators.
3537 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3538 * orientation, i.e. the volume is always positive.
3539 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3540 * nodes and one time. The caller is to delete this array using decrRef() as
3541 * it is no more needed.
3543 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3545 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3546 std::string name="MeasureOnNodeOfMesh_";
3548 int nbNodes=getNumberOfNodes();
3549 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3550 double cst=1./((double)getMeshDimension()+1.);
3551 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3552 array->alloc(nbNodes,1);
3553 double *valsToFill=array->getPointer();
3554 std::fill(valsToFill,valsToFill+nbNodes,0.);
3555 const double *values=tmp->getArray()->getConstPointer();
3556 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3557 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3558 getReverseNodalConnectivity(da,daInd);
3559 const int *daPtr=da->getConstPointer();
3560 const int *daIPtr=daInd->getConstPointer();
3561 for(int i=0;i<nbNodes;i++)
3562 for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3563 valsToFill[i]+=cst*values[*cell];
3565 ret->setArray(array);
3570 * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3571 * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3572 * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3573 * and are normalized.
3574 * <br> \a this can be either
3575 * - a 2D mesh in 2D or 3D space or
3576 * - an 1D mesh in 2D space.
3578 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3579 * cells and one time. The caller is to delete this field using decrRef() as
3580 * it is no more needed.
3581 * \throw If the nodal connectivity of cells is not defined.
3582 * \throw If the coordinates array is not set.
3583 * \throw If the mesh dimension is not set.
3584 * \throw If the mesh and space dimension is not as specified above.
3586 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3588 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3589 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3590 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3591 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3592 int nbOfCells=getNumberOfCells();
3593 int nbComp=getMeshDimension()+1;
3594 array->alloc(nbOfCells,nbComp);
3595 double *vals=array->getPointer();
3596 const int *connI=_nodal_connec_index->getConstPointer();
3597 const int *conn=_nodal_connec->getConstPointer();
3598 const double *coords=_coords->getConstPointer();
3599 if(getMeshDimension()==2)
3601 if(getSpaceDimension()==3)
3603 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3604 const double *locPtr=loc->getConstPointer();
3605 for(int i=0;i<nbOfCells;i++,vals+=3)
3607 int offset=connI[i];
3608 INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3609 double n=INTERP_KERNEL::norm<3>(vals);
3610 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3615 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3616 const double *isAbsPtr=isAbs->getArray()->begin();
3617 for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3618 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3621 else//meshdimension==1
3624 for(int i=0;i<nbOfCells;i++)
3626 int offset=connI[i];
3627 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3628 double n=INTERP_KERNEL::norm<2>(tmp);
3629 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3634 ret->setArray(array);
3636 ret->synchronizeTimeWithSupport();
3641 * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3642 * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3643 * and are normalized.
3644 * <br> \a this can be either
3645 * - a 2D mesh in 2D or 3D space or
3646 * - an 1D mesh in 2D space.
3648 * This method avoids building explicitly a part of \a this mesh to perform the work.
3649 * \param [in] begin - an array of cell ids of interest.
3650 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3651 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3652 * cells and one time. The caller is to delete this field using decrRef() as
3653 * it is no more needed.
3654 * \throw If the nodal connectivity of cells is not defined.
3655 * \throw If the coordinates array is not set.
3656 * \throw If the mesh dimension is not set.
3657 * \throw If the mesh and space dimension is not as specified above.
3658 * \sa buildOrthogonalField()
3660 * \if ENABLE_EXAMPLES
3661 * \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3662 * \ref py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3665 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3667 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3668 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3669 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3670 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3671 std::size_t nbelems=std::distance(begin,end);
3672 int nbComp=getMeshDimension()+1;
3673 array->alloc((int)nbelems,nbComp);
3674 double *vals=array->getPointer();
3675 const int *connI=_nodal_connec_index->getConstPointer();
3676 const int *conn=_nodal_connec->getConstPointer();
3677 const double *coords=_coords->getConstPointer();
3678 if(getMeshDimension()==2)
3680 if(getSpaceDimension()==3)
3682 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3683 const double *locPtr=loc->getConstPointer();
3684 for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3686 int offset=connI[*i];
3687 INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3688 double n=INTERP_KERNEL::norm<3>(vals);
3689 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3694 for(std::size_t i=0;i<nbelems;i++)
3695 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3698 else//meshdimension==1
3701 for(const int *i=begin;i!=end;i++)
3703 int offset=connI[*i];
3704 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3705 double n=INTERP_KERNEL::norm<2>(tmp);
3706 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3711 ret->setArray(array);
3713 ret->synchronizeTimeWithSupport();
3718 * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3719 * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3720 * and are \b not normalized.
3721 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3722 * cells and one time. The caller is to delete this field using decrRef() as
3723 * it is no more needed.
3724 * \throw If the nodal connectivity of cells is not defined.
3725 * \throw If the coordinates array is not set.
3726 * \throw If \a this->getMeshDimension() != 1.
3727 * \throw If \a this mesh includes cells of type other than SEG2.
3729 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3731 if(getMeshDimension()!=1)
3732 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3733 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3734 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3735 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3736 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3737 int nbOfCells=getNumberOfCells();
3738 int spaceDim=getSpaceDimension();
3739 array->alloc(nbOfCells,spaceDim);
3740 double *pt=array->getPointer();
3741 const double *coo=getCoords()->getConstPointer();
3742 std::vector<int> conn;
3744 for(int i=0;i<nbOfCells;i++)
3747 getNodeIdsOfCell(i,conn);
3748 pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3750 ret->setArray(array);
3752 ret->synchronizeTimeWithSupport();
3757 * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3758 * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3759 * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3760 * from. If a result face is shared by two 3D cells, then the face in included twice in
3762 * \param [in] origin - 3 components of a point defining location of the plane.
3763 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3764 * must be greater than 1e-6.
3765 * \param [in] eps - half-thickness of the plane.
3766 * \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3767 * producing correspondent 2D cells. The caller is to delete this array
3768 * using decrRef() as it is no more needed.
3769 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3770 * not share the node coordinates array with \a this mesh. The caller is to
3771 * delete this mesh using decrRef() as it is no more needed.
3772 * \throw If the coordinates array is not set.
3773 * \throw If the nodal connectivity of cells is not defined.
3774 * \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3775 * \throw If magnitude of \a vec is less than 1e-6.
3776 * \throw If the plane does not intersect any 3D cell of \a this mesh.
3777 * \throw If \a this includes quadratic cells.
3779 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3781 checkFullyDefined();
3782 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3783 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3784 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3785 if(candidates->empty())
3786 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3787 std::vector<int> nodes;
3788 DataArrayInt *cellIds1D=0;
3789 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3790 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3791 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3792 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3793 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3794 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3795 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3796 revDesc2=0; revDescIndx2=0;
3797 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3798 revDesc1=0; revDescIndx1=0;
3799 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3800 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3802 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3803 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3805 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3806 std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3807 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3808 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3809 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3810 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3811 connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3812 subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3813 if(cellIds2->empty())
3814 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3815 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3816 ret->setCoords(mDesc1->getCoords());
3817 ret->setConnectivity(conn,connI,true);
3818 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3823 * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3824 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
3825 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3827 * \param [in] origin - 3 components of a point defining location of the plane.
3828 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3829 * must be greater than 1e-6.
3830 * \param [in] eps - half-thickness of the plane.
3831 * \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3832 * producing correspondent segments. The caller is to delete this array
3833 * using decrRef() as it is no more needed.
3834 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3835 * mesh in 3D space. This mesh does not share the node coordinates array with
3836 * \a this mesh. The caller is to delete this mesh using decrRef() as it is
3838 * \throw If the coordinates array is not set.
3839 * \throw If the nodal connectivity of cells is not defined.
3840 * \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3841 * \throw If magnitude of \a vec is less than 1e-6.
3842 * \throw If the plane does not intersect any 2D cell of \a this mesh.
3843 * \throw If \a this includes quadratic cells.
3845 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3847 checkFullyDefined();
3848 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3849 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3850 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3851 if(candidates->empty())
3852 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3853 std::vector<int> nodes;
3854 DataArrayInt *cellIds1D=0;
3855 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3856 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3857 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3858 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3859 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3860 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3861 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3862 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3863 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3865 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3866 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3868 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3869 int ncellsSub=subMesh->getNumberOfCells();
3870 std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3871 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3872 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3873 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3874 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3876 const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3877 const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3878 for(int i=0;i<ncellsSub;i++)
3880 if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3882 if(cut3DSurf[i].first!=-2)
3884 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3885 connI->pushBackSilent(conn->getNumberOfTuples());
3886 cellIds2->pushBackSilent(i);
3890 int cellId3DSurf=cut3DSurf[i].second;
3891 int offset=nodalI[cellId3DSurf]+1;
3892 int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3893 for(int j=0;j<nbOfEdges;j++)
3895 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3896 connI->pushBackSilent(conn->getNumberOfTuples());
3897 cellIds2->pushBackSilent(cellId3DSurf);
3902 if(cellIds2->empty())
3903 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3904 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3905 ret->setCoords(mDesc1->getCoords());
3906 ret->setConnectivity(conn,connI,true);
3907 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3912 * Finds cells whose bounding boxes intersect a given plane.
3913 * \param [in] origin - 3 components of a point defining location of the plane.
3914 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3915 * must be greater than 1e-6.
3916 * \param [in] eps - half-thickness of the plane.
3917 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3918 * cells. The caller is to delete this array using decrRef() as it is no more
3920 * \throw If the coordinates array is not set.
3921 * \throw If the nodal connectivity of cells is not defined.
3922 * \throw If \a this->getSpaceDimension() != 3.
3923 * \throw If magnitude of \a vec is less than 1e-6.
3924 * \sa buildSlice3D()
3926 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3928 checkFullyDefined();
3929 if(getSpaceDimension()!=3)
3930 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3931 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3933 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3935 vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3936 double angle=acos(vec[2]/normm);
3937 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3941 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3942 double normm2(sqrt(vec2[0]*vec2[0]+vec2[1]*vec2[1]+vec2[2]*vec2[2]));
3943 if(normm2/normm>1e-6)
3944 MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3945 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3947 mw->getBoundingBox(bbox);
3948 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3949 cellIds=mw->getCellsInBoundingBox(bbox,eps);
3953 getBoundingBox(bbox);
3954 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3955 cellIds=getCellsInBoundingBox(bbox,eps);
3957 return cellIds.retn();
3961 * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3962 * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3963 * No consideration of coordinate is done by this method.
3964 * 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)
3965 * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3967 bool MEDCouplingUMesh::isContiguous1D() const
3969 if(getMeshDimension()!=1)
3970 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3971 int nbCells=getNumberOfCells();
3973 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3974 const int *connI=_nodal_connec_index->getConstPointer();
3975 const int *conn=_nodal_connec->getConstPointer();
3976 int ref=conn[connI[0]+2];
3977 for(int i=1;i<nbCells;i++)
3979 if(conn[connI[i]+1]!=ref)
3981 ref=conn[connI[i]+2];
3987 * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3988 * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3989 * \param pt reference point of the line
3990 * \param v normalized director vector of the line
3991 * \param eps max precision before throwing an exception
3992 * \param res output of size this->getNumberOfCells
3994 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3996 if(getMeshDimension()!=1)
3997 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3998 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3999 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
4000 if(getSpaceDimension()!=3)
4001 throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
4002 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
4003 const double *fPtr=f->getArray()->getConstPointer();
4005 for(int i=0;i<getNumberOfCells();i++)
4007 const double *tmp1=fPtr+3*i;
4008 tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
4009 tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
4010 tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
4011 double n1=INTERP_KERNEL::norm<3>(tmp);
4012 n1/=INTERP_KERNEL::norm<3>(tmp1);
4014 throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
4016 const double *coo=getCoords()->getConstPointer();
4017 for(int i=0;i<getNumberOfNodes();i++)
4019 std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
4020 std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
4021 res[i]=std::accumulate(tmp,tmp+3,0.);
4026 * 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.
4027 * \a this is expected to be a mesh so that its space dimension is equal to its
4028 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4029 * 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).
4031 * 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
4032 * 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).
4033 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4035 * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
4036 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4038 * \param [in] ptBg the start pointer (included) of the coordinates of the point
4039 * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
4040 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4041 * \return the positive value of the distance.
4042 * \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
4044 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
4046 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
4048 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4049 if(meshDim!=spaceDim-1)
4050 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
4051 if(meshDim!=2 && meshDim!=1)
4052 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4053 checkFullyDefined();
4054 if((int)std::distance(ptBg,ptEnd)!=spaceDim)
4055 { 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()); }
4056 DataArrayInt *ret1=0;
4057 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
4058 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
4059 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
4060 cellId=*ret1Safe->begin();
4061 return *ret0->begin();
4065 * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
4066 * to \a this and the first \a cellId in \a this corresponding to the returned distance.
4067 * 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
4068 * 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).
4069 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4071 * \a this is expected to be a mesh so that its space dimension is equal to its
4072 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4073 * 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).
4075 * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
4076 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4078 * \param [in] pts the list of points in which each tuple represents a point
4079 * \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.
4080 * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
4081 * \throw if number of components of \a pts is not equal to the space dimension.
4082 * \throw if mesh dimension of \a this is not equal to space dimension - 1.
4083 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
4085 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
4088 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
4089 pts->checkAllocated();
4090 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4091 if(meshDim!=spaceDim-1)
4092 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
4093 if(meshDim!=2 && meshDim!=1)
4094 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
4095 if(pts->getNumberOfComponents()!=spaceDim)
4097 std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
4098 throw INTERP_KERNEL::Exception(oss.str().c_str());
4100 checkFullyDefined();
4101 int nbCells=getNumberOfCells();
4103 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4104 int nbOfPts=pts->getNumberOfTuples();
4105 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4106 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4107 const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4108 double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4109 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4110 const double *bbox(bboxArr->begin());
4115 BBTreeDst<3> myTree(bbox,0,0,nbCells);
4116 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4118 double x=std::numeric_limits<double>::max();
4119 std::vector<int> elems;
4120 myTree.getMinDistanceOfMax(ptsPtr,x);
4121 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4122 DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4128 BBTreeDst<2> myTree(bbox,0,0,nbCells);
4129 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4131 double x=std::numeric_limits<double>::max();
4132 std::vector<int> elems;
4133 myTree.getMinDistanceOfMax(ptsPtr,x);
4134 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4135 DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4140 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4142 cellIds=ret1.retn();
4147 * \param [in] pt the start pointer (included) of the coordinates of the point
4148 * \param [in] cellIdsBg the start pointer (included) of cellIds
4149 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4150 * \param [in] nc nodal connectivity
4151 * \param [in] ncI nodal connectivity index
4152 * \param [in,out] ret0 the min distance between \a this and the external input point
4153 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4154 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4156 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)
4159 ret0=std::numeric_limits<double>::max();
4160 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4162 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4164 case INTERP_KERNEL::NORM_TRI3:
4166 double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4168 { ret0=tmp; cellId=*zeCell; }
4171 case INTERP_KERNEL::NORM_QUAD4:
4172 case INTERP_KERNEL::NORM_POLYGON:
4174 double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4176 { ret0=tmp; cellId=*zeCell; }
4180 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4186 * \param [in] pt the start pointer (included) of the coordinates of the point
4187 * \param [in] cellIdsBg the start pointer (included) of cellIds
4188 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4189 * \param [in] nc nodal connectivity
4190 * \param [in] ncI nodal connectivity index
4191 * \param [in,out] ret0 the min distance between \a this and the external input point
4192 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4193 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4195 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)
4198 ret0=std::numeric_limits<double>::max();
4199 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4201 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4203 case INTERP_KERNEL::NORM_SEG2:
4205 std::size_t uselessEntry=0;
4206 double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4209 { ret0=tmp; cellId=*zeCell; }
4213 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4219 * Finds cells in contact with a ball (i.e. a point with precision).
4220 * 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.
4221 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4223 * \warning This method is suitable if the caller intends to evaluate only one
4224 * point, for more points getCellsContainingPoints() is recommended as it is
4226 * \param [in] pos - array of coordinates of the ball central point.
4227 * \param [in] eps - ball radius.
4228 * \return int - a smallest id of cells being in contact with the ball, -1 in case
4229 * if there are no such cells.
4230 * \throw If the coordinates array is not set.
4231 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4233 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4235 std::vector<int> elts;
4236 getCellsContainingPoint(pos,eps,elts);
4239 return elts.front();
4243 * Finds cells in contact with a ball (i.e. a point with precision).
4244 * 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.
4245 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4246 * \warning This method is suitable if the caller intends to evaluate only one
4247 * point, for more points getCellsContainingPoints() is recommended as it is
4249 * \param [in] pos - array of coordinates of the ball central point.
4250 * \param [in] eps - ball radius.
4251 * \param [out] elts - vector returning ids of the found cells. It is cleared
4252 * before inserting ids.
4253 * \throw If the coordinates array is not set.
4254 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4256 * \if ENABLE_EXAMPLES
4257 * \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4258 * \ref py_mcumesh_getCellsContainingPoint "Here is a Python example".
4261 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4263 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4264 getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4265 elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4270 namespace ParaMEDMEM
4272 template<const int SPACEDIMM>
4276 static const int MY_SPACEDIM=SPACEDIMM;
4277 static const int MY_MESHDIM=8;
4278 typedef int MyConnType;
4279 static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4281 // useless, but for windows compilation ...
4282 const double* getCoordinatesPtr() const { return 0; }
4283 const int* getConnectivityPtr() const { return 0; }
4284 const int* getConnectivityIndexPtr() const { return 0; }
4285 INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4289 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m)
4291 INTERP_KERNEL::Edge *ret(0);
4292 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]));
4293 m[n0]=bg[0]; m[n1]=bg[1];
4296 case INTERP_KERNEL::NORM_SEG2:
4298 ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4301 case INTERP_KERNEL::NORM_SEG3:
4303 INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4304 INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4305 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4306 // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4307 bool colinearity(inters.areColinears());
4308 delete e1; delete e2;
4310 { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4312 { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4316 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4321 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4323 INTERP_KERNEL::Edge *ret=0;
4326 case INTERP_KERNEL::NORM_SEG2:
4328 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4331 case INTERP_KERNEL::NORM_SEG3:
4333 INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4334 INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4335 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4336 // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4337 bool colinearity=inters.areColinears();
4338 delete e1; delete e2;
4340 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4342 ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4343 mapp2[bg[2]].second=false;
4347 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4353 * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4354 * the global mesh 'mDesc'.
4355 * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4356 * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4358 INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4359 std::map<INTERP_KERNEL::Node *,int>& mapp)
4362 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.
4363 const double *coo=mDesc->getCoords()->getConstPointer();
4364 const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4365 const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4367 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4368 s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4369 for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4371 INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4372 mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4374 INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4375 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4377 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4378 ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4380 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4382 if((*it2).second.second)
4383 mapp[(*it2).second.first]=(*it2).first;
4384 ((*it2).second.first)->decrRef();
4389 INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4393 int locId=nodeId-offset2;
4394 return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4398 int locId=nodeId-offset1;
4399 return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4401 return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4405 * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4407 void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4408 const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4409 /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4411 for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4413 int eltId1=abs(*desc1)-1;
4414 for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4416 std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4417 if(it==mappRev.end())
4419 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4430 template<int SPACEDIM>
4431 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4432 double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4434 elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4435 int *eltsIndexPtr(eltsIndex->getPointer());
4436 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4437 const double *bbox(bboxArr->begin());
4438 int nbOfCells=getNumberOfCells();
4439 const int *conn=_nodal_connec->getConstPointer();
4440 const int *connI=_nodal_connec_index->getConstPointer();
4441 double bb[2*SPACEDIM];
4442 BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4443 for(int i=0;i<nbOfPoints;i++)
4445 eltsIndexPtr[i+1]=eltsIndexPtr[i];
4446 for(int j=0;j<SPACEDIM;j++)
4448 bb[2*j]=pos[SPACEDIM*i+j];
4449 bb[2*j+1]=pos[SPACEDIM*i+j];
4451 std::vector<int> candidates;
4452 myTree.getIntersectingElems(bb,candidates);
4453 for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4455 int sz(connI[(*iter)+1]-connI[*iter]-1);
4456 INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4458 if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4459 status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4463 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4464 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4465 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4466 std::vector<INTERP_KERNEL::Node *> nodes(sz);
4467 INTERP_KERNEL::QuadraticPolygon *pol(0);
4468 for(int j=0;j<sz;j++)
4470 int nodeId(conn[connI[*iter]+1+j]);
4471 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4473 if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4474 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4476 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4477 INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4478 double a(0.),b(0.),c(0.);
4479 a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4480 status=pol->isInOrOut2(n);
4481 delete pol; n->decrRef();
4485 eltsIndexPtr[i+1]++;
4486 elts->pushBackSilent(*iter);
4492 * Finds cells in contact with several balls (i.e. points with precision).
4493 * This method is an extension of getCellContainingPoint() and
4494 * getCellsContainingPoint() for the case of multiple points.
4495 * 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.
4496 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4497 * \param [in] pos - an array of coordinates of points in full interlace mode :
4498 * X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4499 * this->getSpaceDimension() * \a nbOfPoints
4500 * \param [in] nbOfPoints - number of points to locate within \a this mesh.
4501 * \param [in] eps - radius of balls (i.e. the precision).
4502 * \param [out] elts - vector returning ids of found cells.
4503 * \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4504 * dividing cell ids in \a elts into groups each referring to one
4505 * point. Its every element (except the last one) is an index pointing to the
4506 * first id of a group of cells. For example cells in contact with the *i*-th
4507 * point are described by following range of indices:
4508 * [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4509 * \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4510 * Number of cells in contact with the *i*-th point is
4511 * \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4512 * \throw If the coordinates array is not set.
4513 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4515 * \if ENABLE_EXAMPLES
4516 * \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4517 * \ref py_mcumesh_getCellsContainingPoints "Here is a Python example".
4520 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4521 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4523 int spaceDim=getSpaceDimension();
4524 int mDim=getMeshDimension();
4529 const double *coords=_coords->getConstPointer();
4530 getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4537 throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4539 else if(spaceDim==2)
4543 const double *coords=_coords->getConstPointer();
4544 getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4547 throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4549 else if(spaceDim==1)
4553 const double *coords=_coords->getConstPointer();
4554 getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4557 throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4560 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4564 * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4565 * least two its edges intersect each other anywhere except their extremities. An
4566 * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4567 * \param [in,out] cells - a vector returning ids of the found cells. It is not
4568 * cleared before filling in.
4569 * \param [in] eps - precision.
4570 * \throw If \a this->getMeshDimension() != 2.
4571 * \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4573 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4575 const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4576 if(getMeshDimension()!=2)
4577 throw INTERP_KERNEL::Exception(msg);
4578 int spaceDim=getSpaceDimension();
4579 if(spaceDim!=2 && spaceDim!=3)
4580 throw INTERP_KERNEL::Exception(msg);
4581 const int *conn=_nodal_connec->getConstPointer();
4582 const int *connI=_nodal_connec_index->getConstPointer();
4583 int nbOfCells=getNumberOfCells();
4584 std::vector<double> cell2DinS2;
4585 for(int i=0;i<nbOfCells;i++)
4587 int offset=connI[i];
4588 int nbOfNodesForCell=connI[i+1]-offset-1;
4589 if(nbOfNodesForCell<=3)
4591 bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4592 project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4593 if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4600 * This method is typically requested to unbutterfly 2D linear cells in \b this.
4602 * 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.
4603 * 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.
4605 * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4606 * This convex envelop is computed using Jarvis march algorithm.
4607 * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4608 * 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)
4609 * 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.
4611 * \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.
4612 * \sa MEDCouplingUMesh::colinearize2D
4614 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4616 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4617 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D works only for meshDim=2 and spaceDim=2 !");
4618 checkFullyDefined();
4619 const double *coords=getCoords()->getConstPointer();
4620 int nbOfCells=getNumberOfCells();
4621 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4622 nodalConnecIndexOut->alloc(nbOfCells+1,1);
4623 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4624 int *workIndexOut=nodalConnecIndexOut->getPointer();
4626 const int *nodalConnecIn=_nodal_connec->getConstPointer();
4627 const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4628 std::set<INTERP_KERNEL::NormalizedCellType> types;
4629 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4630 isChanged->alloc(0,1);
4631 for(int i=0;i<nbOfCells;i++,workIndexOut++)
4633 int pos=nodalConnecOut->getNumberOfTuples();
4634 if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4635 isChanged->pushBackSilent(i);
4636 types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4637 workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4639 if(isChanged->empty())
4641 setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4643 return isChanged.retn();
4647 * This method is \b NOT const because it can modify \a this.
4648 * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4649 * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4650 * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4651 * \b 1 for translation and rotation around point of 'mesh1D'.
4652 * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.
4654 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4656 checkFullyDefined();
4657 mesh1D->checkFullyDefined();
4658 if(!mesh1D->isContiguous1D())
4659 throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4660 if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4661 throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4662 if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4663 throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4664 if(mesh1D->getMeshDimension()!=1)
4665 throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4667 if(isPresenceOfQuadratic())
4669 if(mesh1D->isFullyQuadratic())
4672 throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4674 int oldNbOfNodes(getNumberOfNodes());
4675 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4680 newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4685 newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4689 throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4691 setCoords(newCoords);
4692 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad));
4698 * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4699 * If it is not the case an exception will be thrown.
4700 * This method is non const because the coordinate of \a this can be appended with some new points issued from
4701 * intersection of plane defined by ('origin','vec').
4702 * This method has one in/out parameter : 'cut3DCurve'.
4703 * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4704 * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4705 * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4706 * This method will throw an exception if \a this contains a non linear segment.
4708 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4710 checkFullyDefined();
4711 if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4712 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4713 int ncells=getNumberOfCells();
4714 int nnodes=getNumberOfNodes();
4715 double vec2[3],vec3[3],vec4[3];
4716 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4718 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4719 vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4720 const int *conn=_nodal_connec->getConstPointer();
4721 const int *connI=_nodal_connec_index->getConstPointer();
4722 const double *coo=_coords->getConstPointer();
4723 std::vector<double> addCoo;
4724 for(int i=0;i<ncells;i++)
4726 if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4728 if(cut3DCurve[i]==-2)
4730 int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4731 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];
4732 double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4733 double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4734 if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4736 const double *st2=coo+3*st;
4737 vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4738 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]));
4739 if(pos>eps && pos<1-eps)
4741 int nNode=((int)addCoo.size())/3;
4742 vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4743 addCoo.insert(addCoo.end(),vec4,vec4+3);
4744 cut3DCurve[i]=nnodes+nNode;
4750 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4754 int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4755 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4756 coo2->alloc(newNbOfNodes,3);
4757 double *tmp=coo2->getPointer();
4758 tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4759 std::copy(addCoo.begin(),addCoo.end(),tmp);
4760 DataArrayDouble::SetArrayIn(coo2,_coords);
4765 * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4766 * \param mesh1D is the input 1D mesh used for translation computation.
4767 * \return newCoords new coords filled by this method.
4769 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4771 int oldNbOfNodes=getNumberOfNodes();
4772 int nbOf1DCells=mesh1D->getNumberOfCells();
4773 int spaceDim=getSpaceDimension();
4774 DataArrayDouble *ret=DataArrayDouble::New();
4775 std::vector<bool> isQuads;
4776 int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4777 ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4778 double *retPtr=ret->getPointer();
4779 const double *coords=getCoords()->getConstPointer();
4780 double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4782 std::vector<double> c;
4786 for(int i=0;i<nbOf1DCells;i++)
4789 mesh1D->getNodeIdsOfCell(i,v);
4791 mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4792 mesh1D->getCoordinatesOfNode(v[0],c);
4793 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4794 for(int j=0;j<oldNbOfNodes;j++)
4795 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4799 mesh1D->getCoordinatesOfNode(v[1],c);
4800 mesh1D->getCoordinatesOfNode(v[0],c);
4801 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4802 for(int j=0;j<oldNbOfNodes;j++)
4803 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4806 ret->copyStringInfoFrom(*getCoords());
4811 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4812 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4813 * \return newCoords new coords filled by this method.
4815 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4817 if(mesh1D->getSpaceDimension()==2)
4818 return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4819 if(mesh1D->getSpaceDimension()==3)
4820 return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4821 throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4825 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4826 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4827 * \return newCoords new coords filled by this method.
4829 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4832 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4833 int oldNbOfNodes=getNumberOfNodes();
4834 int nbOf1DCells=mesh1D->getNumberOfCells();
4836 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4837 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4838 int nbOfLevsInVec=nbOf1DCells+1;
4839 ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4840 double *retPtr=ret->getPointer();
4841 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4842 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4843 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4844 tmp->setCoords(tmp2);
4845 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4846 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4847 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4848 for(int i=1;i<nbOfLevsInVec;i++)
4850 const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4851 const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4852 const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4853 const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4854 tmp->translate(vec);
4855 double tmp3[2],radius,alpha,alpha0;
4856 const double *p0=i+1<nbOfLevsInVec?begin:third;
4857 const double *p1=i+1<nbOfLevsInVec?end:begin;
4858 const double *p2=i+1<nbOfLevsInVec?third:end;
4859 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4860 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]);
4861 double angle=acos(cosangle/(radius*radius));
4862 tmp->rotate(end,0,angle);
4863 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4869 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4870 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4871 * \return newCoords new coords filled by this method.
4873 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4876 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4877 int oldNbOfNodes=getNumberOfNodes();
4878 int nbOf1DCells=mesh1D->getNumberOfCells();
4880 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4881 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4882 int nbOfLevsInVec=nbOf1DCells+1;
4883 ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4884 double *retPtr=ret->getPointer();
4885 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4886 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4887 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4888 tmp->setCoords(tmp2);
4889 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4890 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4891 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4892 for(int i=1;i<nbOfLevsInVec;i++)
4894 const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4895 const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4896 const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4897 const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4898 tmp->translate(vec);
4899 double tmp3[2],radius,alpha,alpha0;
4900 const double *p0=i+1<nbOfLevsInVec?begin:third;
4901 const double *p1=i+1<nbOfLevsInVec?end:begin;
4902 const double *p2=i+1<nbOfLevsInVec?third:end;
4903 double vecPlane[3]={
4904 (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4905 (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4906 (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4908 double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4911 vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4912 double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4913 double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4915 double c2=cos(asin(s2));
4917 {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4918 {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4919 {-vec2[1]*s2, vec2[0]*s2, c2}
4921 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]};
4922 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]};
4923 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]};
4924 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4925 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]);
4926 double angle=acos(cosangle/(radius*radius));
4927 tmp->rotate(end,vecPlane,angle);
4929 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4935 * This method is private because not easy to use for end user. This method is const contrary to
4936 * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4937 * the coords sorted slice by slice.
4938 * \param isQuad specifies presence of quadratic cells.
4940 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4942 int nbOf1DCells(getNumberOfNodes()/nbOfNodesOf1Lev-1);
4943 int nbOf2DCells(getNumberOfCells());
4944 int nbOf3DCells(nbOf2DCells*nbOf1DCells);
4945 MEDCouplingUMesh *ret(MEDCouplingUMesh::New("Extruded",getMeshDimension()+1));
4946 const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
4947 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()),newConnI(DataArrayInt::New());
4948 newConnI->alloc(nbOf3DCells+1,1);
4949 int *newConnIPtr(newConnI->getPointer());
4951 std::vector<int> newc;
4952 for(int j=0;j<nbOf2DCells;j++)
4954 AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4955 *newConnIPtr++=(int)newc.size();
4957 newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4958 int *newConnPtr(newConn->getPointer());
4959 int deltaPerLev(isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev);
4960 newConnIPtr=newConnI->getPointer();
4961 for(int iz=0;iz<nbOf1DCells;iz++)
4964 std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4965 const int *posOfTypeOfCell(newConnIPtr);
4966 for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4968 int icell((int)(iter-newc.begin()));//std::distance unfortunately cannot been called here in C++98
4969 if(icell!=*posOfTypeOfCell)
4972 *newConnPtr=(*iter)+iz*deltaPerLev;
4983 ret->setConnectivity(newConn,newConnI,true);
4984 ret->setCoords(getCoords());
4989 * Checks if \a this mesh is constituted by only quadratic cells.
4990 * \return bool - \c true if there are only quadratic cells in \a this mesh.
4991 * \throw If the coordinates array is not set.
4992 * \throw If the nodal connectivity of cells is not defined.
4994 bool MEDCouplingUMesh::isFullyQuadratic() const
4996 checkFullyDefined();
4998 int nbOfCells=getNumberOfCells();
4999 for(int i=0;i<nbOfCells && ret;i++)
5001 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5002 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5003 ret=cm.isQuadratic();
5009 * Checks if \a this mesh includes any quadratic cell.
5010 * \return bool - \c true if there is at least one quadratic cells in \a this mesh.
5011 * \throw If the coordinates array is not set.
5012 * \throw If the nodal connectivity of cells is not defined.
5014 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
5016 checkFullyDefined();
5018 int nbOfCells=getNumberOfCells();
5019 for(int i=0;i<nbOfCells && !ret;i++)
5021 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5022 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5023 ret=cm.isQuadratic();
5029 * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
5030 * this mesh, it remains unchanged.
5031 * \throw If the coordinates array is not set.
5032 * \throw If the nodal connectivity of cells is not defined.
5034 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
5036 checkFullyDefined();
5037 int nbOfCells=getNumberOfCells();
5039 const int *iciptr=_nodal_connec_index->getConstPointer();
5040 for(int i=0;i<nbOfCells;i++)
5042 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5043 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5044 if(cm.isQuadratic())
5046 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5047 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5048 if(!cml.isDynamic())
5049 delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
5051 delta+=(iciptr[i+1]-iciptr[i]-1)/2;
5056 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5057 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5058 const int *icptr=_nodal_connec->getConstPointer();
5059 newConn->alloc(getMeshLength()-delta,1);
5060 newConnI->alloc(nbOfCells+1,1);
5061 int *ocptr=newConn->getPointer();
5062 int *ociptr=newConnI->getPointer();
5065 for(int i=0;i<nbOfCells;i++,ociptr++)
5067 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
5068 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5069 if(!cm.isQuadratic())
5071 _types.insert(type);
5072 ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5073 ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5077 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5078 _types.insert(typel);
5079 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5080 int newNbOfNodes=cml.getNumberOfNodes();
5082 newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
5083 *ocptr++=(int)typel;
5084 ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5085 ociptr[1]=ociptr[0]+newNbOfNodes+1;
5088 setConnectivity(newConn,newConnI,false);
5092 * This method converts all linear cell in \a this to quadratic one.
5093 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5094 * 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)
5095 * 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.
5096 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5097 * end of the existing coordinates.
5099 * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5100 * corresponding quadratic cells. 1 is those creating the 'most' complex.
5101 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5103 * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5105 * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5107 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5109 DataArrayInt *conn=0,*connI=0;
5110 DataArrayDouble *coords=0;
5111 std::set<INTERP_KERNEL::NormalizedCellType> types;
5112 checkFullyDefined();
5113 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5114 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5115 int meshDim=getMeshDimension();
5116 switch(conversionType)
5122 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5123 connSafe=conn; connISafe=connI; coordsSafe=coords;
5126 ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5127 connSafe=conn; connISafe=connI; coordsSafe=coords;
5130 ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5131 connSafe=conn; connISafe=connI; coordsSafe=coords;
5134 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5142 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5143 connSafe=conn; connISafe=connI; coordsSafe=coords;
5146 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5147 connSafe=conn; connISafe=connI; coordsSafe=coords;
5150 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5151 connSafe=conn; connISafe=connI; coordsSafe=coords;
5154 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5159 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5161 setConnectivity(connSafe,connISafe,false);
5163 setCoords(coordsSafe);
5169 * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
5170 * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
5171 * The nodes to be added in those 2D cells are defined by the pair of \a nodeIdsToAdd and \a nodeIdsIndexToAdd.
5172 * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
5173 * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
5174 * This method can be seen as the opposite method of colinearize2D.
5175 * 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
5176 * to avoid to modify the numbering of existing nodes.
5178 * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
5179 * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
5180 * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
5181 * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
5182 * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
5183 * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
5184 * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
5186 * \sa buildDescendingConnectivity2
5188 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
5189 const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
5191 if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
5192 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
5193 nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
5194 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
5195 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
5196 if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
5197 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
5198 //DataArrayInt *out0(0),*outi0(0);
5199 //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
5200 //MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s(out0),outi0s(outi0);
5201 //out0s=out0s->buildUnique(); out0s->sort(true);
5206 * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5207 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5208 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5210 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5212 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5213 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5214 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5215 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5216 int nbOfCells=getNumberOfCells();
5217 int nbOfNodes=getNumberOfNodes();
5218 const int *cPtr=_nodal_connec->getConstPointer();
5219 const int *icPtr=_nodal_connec_index->getConstPointer();
5220 int lastVal=0,offset=nbOfNodes;
5221 for(int i=0;i<nbOfCells;i++,icPtr++)
5223 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5224 if(type==INTERP_KERNEL::NORM_SEG2)
5226 types.insert(INTERP_KERNEL::NORM_SEG3);
5227 newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5228 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5229 newConn->pushBackSilent(offset++);
5231 newConnI->pushBackSilent(lastVal);
5232 ret->pushBackSilent(i);
5237 lastVal+=(icPtr[1]-icPtr[0]);
5238 newConnI->pushBackSilent(lastVal);
5239 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5242 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5243 coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5247 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
5249 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5250 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5251 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5253 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5254 DataArrayInt *conn1D=0,*conn1DI=0;
5255 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5256 DataArrayDouble *coordsTmp=0;
5257 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5258 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5259 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5260 const int *c1DPtr=conn1D->begin();
5261 const int *c1DIPtr=conn1DI->begin();
5262 int nbOfCells=getNumberOfCells();
5263 const int *cPtr=_nodal_connec->getConstPointer();
5264 const int *icPtr=_nodal_connec_index->getConstPointer();
5266 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5268 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5269 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5270 if(!cm.isQuadratic())
5272 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5273 types.insert(typ2); newConn->pushBackSilent(typ2);
5274 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5275 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5276 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5277 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5278 newConnI->pushBackSilent(lastVal);
5279 ret->pushBackSilent(i);
5284 lastVal+=(icPtr[1]-icPtr[0]);
5285 newConnI->pushBackSilent(lastVal);
5286 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5289 conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5294 * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5295 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5296 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5298 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5300 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5301 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5302 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5305 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5307 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5308 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5310 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5311 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5312 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5314 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5315 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5316 DataArrayInt *conn1D=0,*conn1DI=0;
5317 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5318 DataArrayDouble *coordsTmp=0;
5319 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5320 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5321 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5322 const int *c1DPtr=conn1D->begin();
5323 const int *c1DIPtr=conn1DI->begin();
5324 int nbOfCells=getNumberOfCells();
5325 const int *cPtr=_nodal_connec->getConstPointer();
5326 const int *icPtr=_nodal_connec_index->getConstPointer();
5327 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5328 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5330 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5331 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5332 if(!cm.isQuadratic())
5334 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5335 types.insert(typ2); newConn->pushBackSilent(typ2);
5336 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5337 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5338 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5339 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5340 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5341 newConnI->pushBackSilent(lastVal);
5342 ret->pushBackSilent(i);
5347 lastVal+=(icPtr[1]-icPtr[0]);
5348 newConnI->pushBackSilent(lastVal);
5349 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5352 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5353 coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5358 * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5359 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5360 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5362 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5364 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5365 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5366 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5369 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5371 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5372 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5373 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5374 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5376 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5377 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5378 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5380 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5381 const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5382 DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5383 std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5384 DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5385 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5386 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5387 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5388 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5389 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5390 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5391 const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5392 int nbOfCells=getNumberOfCells();
5393 const int *cPtr=_nodal_connec->getConstPointer();
5394 const int *icPtr=_nodal_connec_index->getConstPointer();
5395 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5396 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5398 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5399 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5400 if(!cm.isQuadratic())
5402 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5403 if(typ2==INTERP_KERNEL::NORM_ERROR)
5405 std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5406 throw INTERP_KERNEL::Exception(oss.str().c_str());
5408 types.insert(typ2); newConn->pushBackSilent(typ2);
5409 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5410 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5411 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5412 for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5414 int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5415 int tmpPos=newConn->getNumberOfTuples();
5416 newConn->pushBackSilent(nodeId2);
5417 ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5419 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5420 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5421 newConnI->pushBackSilent(lastVal);
5422 ret->pushBackSilent(i);
5427 lastVal+=(icPtr[1]-icPtr[0]);
5428 newConnI->pushBackSilent(lastVal);
5429 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5432 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5433 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5434 coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5435 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5436 std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5437 int *c=newConn->getPointer();
5438 const int *cI(newConnI->begin());
5439 for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5440 c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5441 offset=coordsTmp2Safe->getNumberOfTuples();
5442 for(const int *elt=ret->begin();elt!=ret->end();elt++)
5443 c[cI[(*elt)+1]-1]+=offset;
5444 coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5449 * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5450 * so that the number of cells remains the same. Quadratic faces are converted to
5451 * polygons. This method works only for 2D meshes in
5452 * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5453 * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5454 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5455 * \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5456 * a polylinized edge constituting the input polygon.
5457 * \throw If the coordinates array is not set.
5458 * \throw If the nodal connectivity of cells is not defined.
5459 * \throw If \a this->getMeshDimension() != 2.
5460 * \throw If \a this->getSpaceDimension() != 2.
5462 void MEDCouplingUMesh::tessellate2D(double eps)
5464 checkFullyDefined();
5465 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
5466 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5467 double epsa=fabs(eps);
5468 if(epsa<std::numeric_limits<double>::min())
5469 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 !");
5470 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5471 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5472 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5473 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5474 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5475 revDesc1=0; revDescIndx1=0;
5476 mDesc->tessellate2DCurve(eps);
5477 subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5478 setCoords(mDesc->getCoords());
5482 * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5483 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5484 * \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5485 * a sub-divided edge.
5486 * \throw If the coordinates array is not set.
5487 * \throw If the nodal connectivity of cells is not defined.
5488 * \throw If \a this->getMeshDimension() != 1.
5489 * \throw If \a this->getSpaceDimension() != 2.
5491 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5493 checkFullyDefined();
5494 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5495 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5496 double epsa=fabs(eps);
5497 if(epsa<std::numeric_limits<double>::min())
5498 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 !");
5499 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5500 int nbCells=getNumberOfCells();
5501 int nbNodes=getNumberOfNodes();
5502 const int *conn=_nodal_connec->getConstPointer();
5503 const int *connI=_nodal_connec_index->getConstPointer();
5504 const double *coords=_coords->getConstPointer();
5505 std::vector<double> addCoo;
5506 std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5507 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5508 newConnI->alloc(nbCells+1,1);
5509 int *newConnIPtr=newConnI->getPointer();
5512 INTERP_KERNEL::Node *tmp2[3];
5513 std::set<INTERP_KERNEL::NormalizedCellType> types;
5514 for(int i=0;i<nbCells;i++,newConnIPtr++)
5516 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5517 if(cm.isQuadratic())
5518 {//assert(connI[i+1]-connI[i]-1==3)
5519 tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5520 tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5521 tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5522 tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5523 INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5526 eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5527 types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5529 newConnIPtr[1]=(int)newConn.size();
5533 types.insert(INTERP_KERNEL::NORM_SEG2);
5534 newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5535 newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5536 newConnIPtr[1]=newConnIPtr[0]+3;
5541 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5542 newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5543 newConnIPtr[1]=newConnIPtr[0]+3;
5546 if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5549 DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5550 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5551 newConnArr->alloc((int)newConn.size(),1);
5552 std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5553 DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5554 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5555 newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5556 double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5557 std::copy(addCoo.begin(),addCoo.end(),work);
5558 DataArrayDouble::SetArrayIn(newCoords,_coords);
5563 * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5564 * In addition, returns an array mapping new cells to old ones. <br>
5565 * This method typically increases the number of cells in \a this mesh
5566 * but the number of nodes remains \b unchanged.
5567 * That's why the 3D splitting policies
5568 * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5569 * \param [in] policy - specifies a pattern used for splitting.
5570 * The semantic of \a policy is:
5571 * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5572 * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5573 * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8 into 5 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5574 * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8 into 6 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5577 * \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5578 * an id of old cell producing it. The caller is to delete this array using
5579 * decrRef() as it is no more needed.
5581 * \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5582 * \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5583 * and \a this->getMeshDimension() != 3.
5584 * \throw If \a policy is not one of the four discussed above.
5585 * \throw If the nodal connectivity of cells is not defined.
5586 * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5588 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5593 return simplexizePol0();
5595 return simplexizePol1();
5596 case (int) INTERP_KERNEL::PLANAR_FACE_5:
5597 return simplexizePlanarFace5();
5598 case (int) INTERP_KERNEL::PLANAR_FACE_6:
5599 return simplexizePlanarFace6();
5601 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)");
5606 * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5607 * - 1D: INTERP_KERNEL::NORM_SEG2
5608 * - 2D: INTERP_KERNEL::NORM_TRI3
5609 * - 3D: INTERP_KERNEL::NORM_TETRA4.
5611 * This method is useful for users that need to use P1 field services as
5612 * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5613 * All these methods need mesh support containing only simplex cells.
5614 * \return bool - \c true if there are only simplex cells in \a this mesh.
5615 * \throw If the coordinates array is not set.
5616 * \throw If the nodal connectivity of cells is not defined.
5617 * \throw If \a this->getMeshDimension() < 1.
5619 bool MEDCouplingUMesh::areOnlySimplexCells() const
5621 checkFullyDefined();
5622 int mdim=getMeshDimension();
5623 if(mdim<1 || mdim>3)
5624 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5625 int nbCells=getNumberOfCells();
5626 const int *conn=_nodal_connec->getConstPointer();
5627 const int *connI=_nodal_connec_index->getConstPointer();
5628 for(int i=0;i<nbCells;i++)
5630 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5638 * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5640 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5642 checkConnectivityFullyDefined();
5643 if(getMeshDimension()!=2)
5644 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5645 int nbOfCells=getNumberOfCells();
5646 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5647 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5648 ret->alloc(nbOfCells+nbOfCutCells,1);
5649 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5650 int *retPt=ret->getPointer();
5651 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5652 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5653 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5654 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5655 int *pt=newConn->getPointer();
5656 int *ptI=newConnI->getPointer();
5658 const int *oldc=_nodal_connec->getConstPointer();
5659 const int *ci=_nodal_connec_index->getConstPointer();
5660 for(int i=0;i<nbOfCells;i++,ci++)
5662 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5664 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5665 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5666 pt=std::copy(tmp,tmp+8,pt);
5675 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5676 ptI[1]=ptI[0]+ci[1]-ci[0];
5681 _nodal_connec->decrRef();
5682 _nodal_connec=newConn.retn();
5683 _nodal_connec_index->decrRef();
5684 _nodal_connec_index=newConnI.retn();
5691 * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5693 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5695 checkConnectivityFullyDefined();
5696 if(getMeshDimension()!=2)
5697 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5698 int nbOfCells=getNumberOfCells();
5699 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5700 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5701 ret->alloc(nbOfCells+nbOfCutCells,1);
5702 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5703 int *retPt=ret->getPointer();
5704 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5705 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5706 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5707 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5708 int *pt=newConn->getPointer();
5709 int *ptI=newConnI->getPointer();
5711 const int *oldc=_nodal_connec->getConstPointer();
5712 const int *ci=_nodal_connec_index->getConstPointer();
5713 for(int i=0;i<nbOfCells;i++,ci++)
5715 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5717 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5718 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5719 pt=std::copy(tmp,tmp+8,pt);
5728 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5729 ptI[1]=ptI[0]+ci[1]-ci[0];
5734 _nodal_connec->decrRef();
5735 _nodal_connec=newConn.retn();
5736 _nodal_connec_index->decrRef();
5737 _nodal_connec_index=newConnI.retn();
5744 * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5746 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5748 checkConnectivityFullyDefined();
5749 if(getMeshDimension()!=3)
5750 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5751 int nbOfCells=getNumberOfCells();
5752 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5753 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5754 ret->alloc(nbOfCells+4*nbOfCutCells,1);
5755 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5756 int *retPt=ret->getPointer();
5757 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5758 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5759 newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5760 newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5761 int *pt=newConn->getPointer();
5762 int *ptI=newConnI->getPointer();
5764 const int *oldc=_nodal_connec->getConstPointer();
5765 const int *ci=_nodal_connec_index->getConstPointer();
5766 for(int i=0;i<nbOfCells;i++,ci++)
5768 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5770 for(int j=0;j<5;j++,pt+=5,ptI++)
5772 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5773 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];
5780 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5781 ptI[1]=ptI[0]+ci[1]-ci[0];
5786 _nodal_connec->decrRef();
5787 _nodal_connec=newConn.retn();
5788 _nodal_connec_index->decrRef();
5789 _nodal_connec_index=newConnI.retn();
5796 * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5798 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5800 checkConnectivityFullyDefined();
5801 if(getMeshDimension()!=3)
5802 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5803 int nbOfCells=getNumberOfCells();
5804 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5805 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5806 ret->alloc(nbOfCells+5*nbOfCutCells,1);
5807 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5808 int *retPt=ret->getPointer();
5809 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5810 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5811 newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5812 newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5813 int *pt=newConn->getPointer();
5814 int *ptI=newConnI->getPointer();
5816 const int *oldc=_nodal_connec->getConstPointer();
5817 const int *ci=_nodal_connec_index->getConstPointer();
5818 for(int i=0;i<nbOfCells;i++,ci++)
5820 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5822 for(int j=0;j<6;j++,pt+=5,ptI++)
5824 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5825 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];
5832 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5833 ptI[1]=ptI[0]+ci[1]-ci[0];
5838 _nodal_connec->decrRef();
5839 _nodal_connec=newConn.retn();
5840 _nodal_connec_index->decrRef();
5841 _nodal_connec_index=newConnI.retn();
5848 * 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.
5849 * This method completly ignore coordinates.
5850 * \param nodeSubdived is the nodal connectivity of subdivision of edges
5851 * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5852 * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5853 * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5855 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5857 checkFullyDefined();
5858 if(getMeshDimension()!=2)
5859 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5860 int nbOfCells=getNumberOfCells();
5861 int *connI=_nodal_connec_index->getPointer();
5863 for(int i=0;i<nbOfCells;i++,connI++)
5865 int offset=descIndex[i];
5866 int nbOfEdges=descIndex[i+1]-offset;
5868 bool ddirect=desc[offset+nbOfEdges-1]>0;
5869 int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5870 int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5871 for(int j=0;j<nbOfEdges;j++)
5873 bool direct=desc[offset+j]>0;
5874 int edgeId=std::abs(desc[offset+j])-1;
5875 if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5877 int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5878 int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5879 int ref2=direct?id1:id2;
5882 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5883 newConnLgth+=nbOfSubNodes-1;
5888 std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5889 throw INTERP_KERNEL::Exception(oss.str().c_str());
5894 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5897 newConnLgth++;//+1 is for cell type
5898 connI[1]=newConnLgth;
5901 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5902 newConn->alloc(newConnLgth,1);
5903 int *work=newConn->getPointer();
5904 for(int i=0;i<nbOfCells;i++)
5906 *work++=INTERP_KERNEL::NORM_POLYGON;
5907 int offset=descIndex[i];
5908 int nbOfEdges=descIndex[i+1]-offset;
5909 for(int j=0;j<nbOfEdges;j++)
5911 bool direct=desc[offset+j]>0;
5912 int edgeId=std::abs(desc[offset+j])-1;
5914 work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5917 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5918 std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5919 work=std::copy(it,it+nbOfSubNodes-1,work);
5923 DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5926 _types.insert(INTERP_KERNEL::NORM_POLYGON);
5930 * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5931 * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5932 * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5933 * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5934 * so it can be useful to call mergeNodes() before calling this method.
5935 * \throw If \a this->getMeshDimension() <= 1.
5936 * \throw If the coordinates array is not set.
5937 * \throw If the nodal connectivity of cells is not defined.
5939 void MEDCouplingUMesh::convertDegeneratedCells()
5941 checkFullyDefined();
5942 if(getMeshDimension()<=1)
5943 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5944 int nbOfCells=getNumberOfCells();
5947 int initMeshLgth=getMeshLength();
5948 int *conn=_nodal_connec->getPointer();
5949 int *index=_nodal_connec_index->getPointer();
5953 for(int i=0;i<nbOfCells;i++)
5955 lgthOfCurCell=index[i+1]-posOfCurCell;
5956 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5958 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5959 conn+newPos+1,newLgth);
5960 conn[newPos]=newType;
5962 posOfCurCell=index[i+1];
5965 if(newPos!=initMeshLgth)
5966 _nodal_connec->reAlloc(newPos);
5971 * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5972 * A cell is considered to be oriented correctly if an angle between its
5973 * normal vector and a given vector is less than \c PI / \c 2.
5974 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5976 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5978 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5979 * is not cleared before filling in.
5980 * \throw If \a this->getMeshDimension() != 2.
5981 * \throw If \a this->getSpaceDimension() != 3.
5983 * \if ENABLE_EXAMPLES
5984 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5985 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5988 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
5990 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5991 throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5992 int nbOfCells=getNumberOfCells();
5993 const int *conn=_nodal_connec->getConstPointer();
5994 const int *connI=_nodal_connec_index->getConstPointer();
5995 const double *coordsPtr=_coords->getConstPointer();
5996 for(int i=0;i<nbOfCells;i++)
5998 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5999 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6001 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
6002 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6009 * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
6010 * considered to be oriented correctly if an angle between its normal vector and a
6011 * given vector is less than \c PI / \c 2.
6012 * \param [in] vec - 3 components of the vector specifying the correct orientation of
6014 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
6016 * \throw If \a this->getMeshDimension() != 2.
6017 * \throw If \a this->getSpaceDimension() != 3.
6019 * \if ENABLE_EXAMPLES
6020 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
6021 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
6024 * \sa changeOrientationOfCells
6026 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
6028 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6029 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
6030 int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6031 const int *connI(_nodal_connec_index->getConstPointer());
6032 const double *coordsPtr(_coords->getConstPointer());
6033 bool isModified(false);
6034 for(int i=0;i<nbOfCells;i++)
6036 INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6037 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6039 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6040 bool isQuadratic(cm.isQuadratic());
6041 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6044 cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6049 _nodal_connec->declareAsNew();
6054 * This method change the orientation of cells in \a this without any consideration of coordinates. Only connectivity is impacted.
6056 * \sa orientCorrectly2DCells
6058 void MEDCouplingUMesh::changeOrientationOfCells()
6060 int mdim(getMeshDimension());
6061 if(mdim!=2 && mdim!=1)
6062 throw INTERP_KERNEL::Exception("Invalid mesh to apply changeOrientationOfCells on it : must be meshDim==2 or meshDim==1 !");
6063 int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6064 const int *connI(_nodal_connec_index->getConstPointer());
6067 for(int i=0;i<nbOfCells;i++)
6069 INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6070 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6071 cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6076 for(int i=0;i<nbOfCells;i++)
6078 INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6079 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6080 cm.changeOrientationOf1D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6086 * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
6087 * oriented facets. The normal vector of the facet should point out of the cell.
6088 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6089 * is not cleared before filling in.
6090 * \throw If \a this->getMeshDimension() != 3.
6091 * \throw If \a this->getSpaceDimension() != 3.
6092 * \throw If the coordinates array is not set.
6093 * \throw If the nodal connectivity of cells is not defined.
6095 * \if ENABLE_EXAMPLES
6096 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6097 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6100 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
6102 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6103 throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
6104 int nbOfCells=getNumberOfCells();
6105 const int *conn=_nodal_connec->getConstPointer();
6106 const int *connI=_nodal_connec_index->getConstPointer();
6107 const double *coordsPtr=_coords->getConstPointer();
6108 for(int i=0;i<nbOfCells;i++)
6110 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6111 if(type==INTERP_KERNEL::NORM_POLYHED)
6113 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6120 * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6122 * \throw If \a this->getMeshDimension() != 3.
6123 * \throw If \a this->getSpaceDimension() != 3.
6124 * \throw If the coordinates array is not set.
6125 * \throw If the nodal connectivity of cells is not defined.
6126 * \throw If the reparation fails.
6128 * \if ENABLE_EXAMPLES
6129 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6130 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6132 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6134 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
6136 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6137 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6138 int nbOfCells=getNumberOfCells();
6139 int *conn=_nodal_connec->getPointer();
6140 const int *connI=_nodal_connec_index->getConstPointer();
6141 const double *coordsPtr=_coords->getConstPointer();
6142 for(int i=0;i<nbOfCells;i++)
6144 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6145 if(type==INTERP_KERNEL::NORM_POLYHED)
6149 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6150 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6152 catch(INTERP_KERNEL::Exception& e)
6154 std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6155 throw INTERP_KERNEL::Exception(oss.str().c_str());
6163 * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6164 * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6165 * according to which the first facet of the cell should be oriented to have the normal vector
6166 * pointing out of cell.
6167 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6168 * cells. The caller is to delete this array using decrRef() as it is no more
6170 * \throw If \a this->getMeshDimension() != 3.
6171 * \throw If \a this->getSpaceDimension() != 3.
6172 * \throw If the coordinates array is not set.
6173 * \throw If the nodal connectivity of cells is not defined.
6175 * \if ENABLE_EXAMPLES
6176 * \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6177 * \ref py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6179 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6181 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6183 const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6184 if(getMeshDimension()!=3)
6185 throw INTERP_KERNEL::Exception(msg);
6186 int spaceDim=getSpaceDimension();
6188 throw INTERP_KERNEL::Exception(msg);
6190 int nbOfCells=getNumberOfCells();
6191 int *conn=_nodal_connec->getPointer();
6192 const int *connI=_nodal_connec_index->getConstPointer();
6193 const double *coo=getCoords()->getConstPointer();
6194 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6195 for(int i=0;i<nbOfCells;i++)
6197 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6198 if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6200 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6202 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6203 cells->pushBackSilent(i);
6207 return cells.retn();
6211 * This method is a faster method to correct orientation of all 3D cells in \a this.
6212 * 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.
6213 * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6215 * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6216 * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons,
6218 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6220 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6221 throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6222 int nbOfCells=getNumberOfCells();
6223 int *conn=_nodal_connec->getPointer();
6224 const int *connI=_nodal_connec_index->getConstPointer();
6225 const double *coordsPtr=_coords->getConstPointer();
6226 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6227 for(int i=0;i<nbOfCells;i++)
6229 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6232 case INTERP_KERNEL::NORM_TETRA4:
6234 if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6236 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6237 ret->pushBackSilent(i);
6241 case INTERP_KERNEL::NORM_PYRA5:
6243 if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6245 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6246 ret->pushBackSilent(i);
6250 case INTERP_KERNEL::NORM_PENTA6:
6251 case INTERP_KERNEL::NORM_HEXA8:
6252 case INTERP_KERNEL::NORM_HEXGP12:
6254 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6256 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6257 ret->pushBackSilent(i);
6261 case INTERP_KERNEL::NORM_POLYHED:
6263 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6265 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6266 ret->pushBackSilent(i);
6271 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 !");
6279 * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6280 * If it is not the case an exception will be thrown.
6281 * This method is fast because the first cell of \a this is used to compute the plane.
6282 * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6283 * \param pos output of size at least 3 used to store a point owned of searched plane.
6285 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6287 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6288 throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6289 const int *conn=_nodal_connec->getConstPointer();
6290 const int *connI=_nodal_connec_index->getConstPointer();
6291 const double *coordsPtr=_coords->getConstPointer();
6292 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6293 std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6297 * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6298 * cells. Currently cells of the following types are treated:
6299 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6300 * For a cell of other type an exception is thrown.
6301 * Space dimension of a 2D mesh can be either 2 or 3.
6302 * The Edge Ratio of a cell \f$t\f$ is:
6303 * \f$\frac{|t|_\infty}{|t|_0}\f$,
6304 * where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6305 * the smallest edge lengths of \f$t\f$.
6306 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6307 * cells and one time, lying on \a this mesh. The caller is to delete this
6308 * field using decrRef() as it is no more needed.
6309 * \throw If the coordinates array is not set.
6310 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6311 * \throw If the connectivity data array has more than one component.
6312 * \throw If the connectivity data array has a named component.
6313 * \throw If the connectivity index data array has more than one component.
6314 * \throw If the connectivity index data array has a named component.
6315 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6316 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6317 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6319 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6322 int spaceDim=getSpaceDimension();
6323 int meshDim=getMeshDimension();
6324 if(spaceDim!=2 && spaceDim!=3)
6325 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6326 if(meshDim!=2 && meshDim!=3)
6327 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6328 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6330 int nbOfCells=getNumberOfCells();
6331 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6332 arr->alloc(nbOfCells,1);
6333 double *pt=arr->getPointer();
6334 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6335 const int *conn=_nodal_connec->getConstPointer();
6336 const int *connI=_nodal_connec_index->getConstPointer();
6337 const double *coo=_coords->getConstPointer();
6339 for(int i=0;i<nbOfCells;i++,pt++)
6341 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6344 case INTERP_KERNEL::NORM_TRI3:
6346 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6347 *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6350 case INTERP_KERNEL::NORM_QUAD4:
6352 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6353 *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6356 case INTERP_KERNEL::NORM_TETRA4:
6358 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6359 *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6363 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6365 conn+=connI[i+1]-connI[i];
6367 ret->setName("EdgeRatio");
6368 ret->synchronizeTimeWithSupport();
6373 * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6374 * cells. Currently cells of the following types are treated:
6375 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6376 * For a cell of other type an exception is thrown.
6377 * Space dimension of a 2D mesh can be either 2 or 3.
6378 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6379 * cells and one time, lying on \a this mesh. The caller is to delete this
6380 * field using decrRef() as it is no more needed.
6381 * \throw If the coordinates array is not set.
6382 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6383 * \throw If the connectivity data array has more than one component.
6384 * \throw If the connectivity data array has a named component.
6385 * \throw If the connectivity index data array has more than one component.
6386 * \throw If the connectivity index data array has a named component.
6387 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6388 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6389 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6391 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6394 int spaceDim=getSpaceDimension();
6395 int meshDim=getMeshDimension();
6396 if(spaceDim!=2 && spaceDim!=3)
6397 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6398 if(meshDim!=2 && meshDim!=3)
6399 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6400 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6402 int nbOfCells=getNumberOfCells();
6403 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6404 arr->alloc(nbOfCells,1);
6405 double *pt=arr->getPointer();
6406 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6407 const int *conn=_nodal_connec->getConstPointer();
6408 const int *connI=_nodal_connec_index->getConstPointer();
6409 const double *coo=_coords->getConstPointer();
6411 for(int i=0;i<nbOfCells;i++,pt++)
6413 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6416 case INTERP_KERNEL::NORM_TRI3:
6418 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6419 *pt=INTERP_KERNEL::triAspectRatio(tmp);
6422 case INTERP_KERNEL::NORM_QUAD4:
6424 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6425 *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6428 case INTERP_KERNEL::NORM_TETRA4:
6430 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6431 *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6435 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6437 conn+=connI[i+1]-connI[i];
6439 ret->setName("AspectRatio");
6440 ret->synchronizeTimeWithSupport();
6445 * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6446 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6447 * treated: INTERP_KERNEL::NORM_QUAD4.
6448 * For a cell of other type an exception is thrown.
6449 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6450 * cells and one time, lying on \a this mesh. The caller is to delete this
6451 * field using decrRef() as it is no more needed.
6452 * \throw If the coordinates array is not set.
6453 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6454 * \throw If the connectivity data array has more than one component.
6455 * \throw If the connectivity data array has a named component.
6456 * \throw If the connectivity index data array has more than one component.
6457 * \throw If the connectivity index data array has a named component.
6458 * \throw If \a this->getMeshDimension() != 2.
6459 * \throw If \a this->getSpaceDimension() != 3.
6460 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6462 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6465 int spaceDim=getSpaceDimension();
6466 int meshDim=getMeshDimension();
6468 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6470 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6471 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6473 int nbOfCells=getNumberOfCells();
6474 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6475 arr->alloc(nbOfCells,1);
6476 double *pt=arr->getPointer();
6477 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6478 const int *conn=_nodal_connec->getConstPointer();
6479 const int *connI=_nodal_connec_index->getConstPointer();
6480 const double *coo=_coords->getConstPointer();
6482 for(int i=0;i<nbOfCells;i++,pt++)
6484 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6487 case INTERP_KERNEL::NORM_QUAD4:
6489 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6490 *pt=INTERP_KERNEL::quadWarp(tmp);
6494 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6496 conn+=connI[i+1]-connI[i];
6498 ret->setName("Warp");
6499 ret->synchronizeTimeWithSupport();
6505 * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6506 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6507 * treated: INTERP_KERNEL::NORM_QUAD4.
6508 * For a cell of other type an exception is thrown.
6509 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6510 * cells and one time, lying on \a this mesh. The caller is to delete this
6511 * field using decrRef() as it is no more needed.
6512 * \throw If the coordinates array is not set.
6513 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6514 * \throw If the connectivity data array has more than one component.
6515 * \throw If the connectivity data array has a named component.
6516 * \throw If the connectivity index data array has more than one component.
6517 * \throw If the connectivity index data array has a named component.
6518 * \throw If \a this->getMeshDimension() != 2.
6519 * \throw If \a this->getSpaceDimension() != 3.
6520 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6522 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6525 int spaceDim=getSpaceDimension();
6526 int meshDim=getMeshDimension();
6528 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6530 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6531 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6533 int nbOfCells=getNumberOfCells();
6534 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6535 arr->alloc(nbOfCells,1);
6536 double *pt=arr->getPointer();
6537 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6538 const int *conn=_nodal_connec->getConstPointer();
6539 const int *connI=_nodal_connec_index->getConstPointer();
6540 const double *coo=_coords->getConstPointer();
6542 for(int i=0;i<nbOfCells;i++,pt++)
6544 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6547 case INTERP_KERNEL::NORM_QUAD4:
6549 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6550 *pt=INTERP_KERNEL::quadSkew(tmp);
6554 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6556 conn+=connI[i+1]-connI[i];
6558 ret->setName("Skew");
6559 ret->synchronizeTimeWithSupport();
6564 * 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.
6566 * \return a new instance of field containing the result. The returned instance has to be deallocated by the caller.
6568 * \sa getSkewField, getWarpField, getAspectRatioField, getEdgeRatioField
6570 MEDCouplingFieldDouble *MEDCouplingUMesh::computeDiameterField() const
6573 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME));
6575 std::set<INTERP_KERNEL::NormalizedCellType> types;
6576 ComputeAllTypesInternal(types,_nodal_connec,_nodal_connec_index);
6577 int spaceDim(getSpaceDimension()),nbCells(getNumberOfCells());
6578 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::New());
6579 arr->alloc(nbCells,1);
6580 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++)
6582 INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::DiameterCalculator> dc(INTERP_KERNEL::CellModel::GetCellModel(*it).buildInstanceOfDiameterCalulator(spaceDim));
6583 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds(giveCellsWithType(*it));
6584 dc->computeForListOfCellIdsUMeshFrmt(cellIds->begin(),cellIds->end(),_nodal_connec_index->begin(),_nodal_connec->begin(),getCoords()->begin(),arr->getPointer());
6587 ret->setName("Diameter");
6592 * This method aggregate the bbox of each cell and put it into bbox parameter.
6594 * \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)
6595 * For all other cases this input parameter is ignored.
6596 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6598 * \throw If \a this is not fully set (coordinates and connectivity).
6599 * \throw If a cell in \a this has no valid nodeId.
6600 * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6602 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6604 int mDim(getMeshDimension()),sDim(getSpaceDimension());
6605 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.
6606 return getBoundingBoxForBBTreeFast();
6607 if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6609 bool presenceOfQuadratic(false);
6610 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6612 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6613 if(cm.isQuadratic())
6614 presenceOfQuadratic=true;
6616 if(!presenceOfQuadratic)
6617 return getBoundingBoxForBBTreeFast();
6618 if(mDim==2 && sDim==2)
6619 return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6621 return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6623 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) !");
6627 * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6628 * So meshes having quadratic cells the computed bounding boxes can be invalid !
6630 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6632 * \throw If \a this is not fully set (coordinates and connectivity).
6633 * \throw If a cell in \a this has no valid nodeId.
6635 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6637 checkFullyDefined();
6638 int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6639 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6640 double *bbox(ret->getPointer());
6641 for(int i=0;i<nbOfCells*spaceDim;i++)
6643 bbox[2*i]=std::numeric_limits<double>::max();
6644 bbox[2*i+1]=-std::numeric_limits<double>::max();
6646 const double *coordsPtr(_coords->getConstPointer());
6647 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6648 for(int i=0;i<nbOfCells;i++)
6650 int offset=connI[i]+1;
6651 int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6652 for(int j=0;j<nbOfNodesForCell;j++)
6654 int nodeId=conn[offset+j];
6655 if(nodeId>=0 && nodeId<nbOfNodes)
6657 for(int k=0;k<spaceDim;k++)
6659 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6660 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6667 std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6668 throw INTERP_KERNEL::Exception(oss.str().c_str());
6675 * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6676 * useful for 2D meshes having quadratic cells
6677 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6678 * the two extremities of the arc of circle).
6680 * \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)
6681 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6682 * \throw If \a this is not fully defined.
6683 * \throw If \a this is not a mesh with meshDimension equal to 2.
6684 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6685 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6687 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6689 checkFullyDefined();
6690 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6691 if(spaceDim!=2 || mDim!=2)
6692 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!");
6693 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6694 double *bbox(ret->getPointer());
6695 const double *coords(_coords->getConstPointer());
6696 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6697 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6699 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6700 int sz(connI[1]-connI[0]-1);
6701 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6702 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6703 INTERP_KERNEL::QuadraticPolygon *pol(0);
6704 for(int j=0;j<sz;j++)
6706 int nodeId(conn[*connI+1+j]);
6707 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6709 if(!cm.isQuadratic())
6710 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6712 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6713 INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6714 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax();
6720 * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6721 * useful for 2D meshes having quadratic cells
6722 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6723 * the two extremities of the arc of circle).
6725 * \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)
6726 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6727 * \throw If \a this is not fully defined.
6728 * \throw If \a this is not a mesh with meshDimension equal to 1.
6729 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6730 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6732 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6734 checkFullyDefined();
6735 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6736 if(spaceDim!=2 || mDim!=1)
6737 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!");
6738 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6739 double *bbox(ret->getPointer());
6740 const double *coords(_coords->getConstPointer());
6741 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6742 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6744 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6745 int sz(connI[1]-connI[0]-1);
6746 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6747 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6748 INTERP_KERNEL::Edge *edge(0);
6749 for(int j=0;j<sz;j++)
6751 int nodeId(conn[*connI+1+j]);
6752 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6754 if(!cm.isQuadratic())
6755 edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6757 edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6758 const INTERP_KERNEL::Bounds& b(edge->getBounds());
6759 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6766 namespace ParaMEDMEMImpl
6771 ConnReader(const int *c, int val):_conn(c),_val(val) { }
6772 bool operator() (const int& pos) { return _conn[pos]!=_val; }
6781 ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6782 bool operator() (const int& pos) { return _conn[pos]==_val; }
6792 * This method expects that \a this is sorted by types. If not an exception will be thrown.
6793 * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6794 * \a this is composed in cell types.
6795 * The returned array is of size 3*n where n is the number of different types present in \a this.
6796 * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here.
6797 * This parameter is kept only for compatibility with other methode listed above.
6799 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6801 checkConnectivityFullyDefined();
6802 const int *conn=_nodal_connec->getConstPointer();
6803 const int *connI=_nodal_connec_index->getConstPointer();
6804 const int *work=connI;
6805 int nbOfCells=getNumberOfCells();
6806 std::size_t n=getAllGeoTypes().size();
6807 std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6808 std::set<INTERP_KERNEL::NormalizedCellType> types;
6809 for(std::size_t i=0;work!=connI+nbOfCells;i++)
6811 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6812 if(types.find(typ)!=types.end())
6814 std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6815 oss << " is not contiguous !";
6816 throw INTERP_KERNEL::Exception(oss.str().c_str());
6820 const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6821 ret[3*i+1]=(int)std::distance(work,work2);
6828 * This method is used to check that this has contiguous cell type in same order than described in \a code.
6829 * only for types cell, type node is not managed.
6830 * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6831 * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6832 * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6833 * If 2 or more same geometric type is in \a code and exception is thrown too.
6835 * This method firstly checks
6836 * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6837 * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6838 * an exception is thrown too.
6840 * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6841 * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown
6842 * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6844 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6847 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6848 std::size_t sz=code.size();
6851 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6852 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6854 bool isNoPflUsed=true;
6855 for(std::size_t i=0;i<n;i++)
6856 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6858 types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6860 if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6861 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6862 isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6865 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6868 if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6869 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6870 if(types.size()==_types.size())
6873 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6875 int *retPtr=ret->getPointer();
6876 const int *connI=_nodal_connec_index->getConstPointer();
6877 const int *conn=_nodal_connec->getConstPointer();
6878 int nbOfCells=getNumberOfCells();
6881 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6883 i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6884 int offset=(int)std::distance(connI,i);
6885 const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6886 int nbOfCellsOfCurType=(int)std::distance(i,j);
6887 if(code[3*kk+2]==-1)
6888 for(int k=0;k<nbOfCellsOfCurType;k++)
6892 int idInIdsPerType=code[3*kk+2];
6893 if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6895 const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6898 zePfl->checkAllocated();
6899 if(zePfl->getNumberOfComponents()==1)
6901 for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6903 if(*k>=0 && *k<nbOfCellsOfCurType)
6904 *retPtr=(*k)+offset;
6907 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6908 oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6909 throw INTERP_KERNEL::Exception(oss.str().c_str());
6914 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6917 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6921 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6922 oss << " should be in [0," << idsPerType.size() << ") !";
6923 throw INTERP_KERNEL::Exception(oss.str().c_str());
6932 * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6933 * 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.
6934 * 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.
6935 * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6937 * \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.
6938 * \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,
6939 * \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6940 * \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.
6941 * This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6942 * \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
6944 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6947 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6948 if(profile->getNumberOfComponents()!=1)
6949 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6950 checkConnectivityFullyDefined();
6951 const int *conn=_nodal_connec->getConstPointer();
6952 const int *connI=_nodal_connec_index->getConstPointer();
6953 int nbOfCells=getNumberOfCells();
6954 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6955 std::vector<int> typeRangeVals(1);
6956 for(const int *i=connI;i!=connI+nbOfCells;)
6958 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6959 if(std::find(types.begin(),types.end(),curType)!=types.end())
6961 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6963 types.push_back(curType);
6964 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6965 typeRangeVals.push_back((int)std::distance(connI,i));
6968 DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6969 profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6970 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6971 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6972 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6974 int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6975 code.resize(3*nbOfCastsFinal);
6976 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6977 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6978 for(int i=0;i<nbOfCastsFinal;i++)
6980 int castId=castsPresent->getIJ(i,0);
6981 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6982 idsInPflPerType2.push_back(tmp3);
6983 code[3*i]=(int)types[castId];
6984 code[3*i+1]=tmp3->getNumberOfTuples();
6985 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6986 if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6988 tmp4->copyStringInfoFrom(*profile);
6989 idsPerType2.push_back(tmp4);
6990 code[3*i+2]=(int)idsPerType2.size()-1;
6997 std::size_t sz2=idsInPflPerType2.size();
6998 idsInPflPerType.resize(sz2);
6999 for(std::size_t i=0;i<sz2;i++)
7001 DataArrayInt *locDa=idsInPflPerType2[i];
7003 idsInPflPerType[i]=locDa;
7005 std::size_t sz=idsPerType2.size();
7006 idsPerType.resize(sz);
7007 for(std::size_t i=0;i<sz;i++)
7009 DataArrayInt *locDa=idsPerType2[i];
7011 idsPerType[i]=locDa;
7016 * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
7017 * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
7018 * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
7019 * 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.
7021 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
7023 checkFullyDefined();
7024 nM1LevMesh->checkFullyDefined();
7025 if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
7026 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
7027 if(_coords!=nM1LevMesh->getCoords())
7028 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
7029 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
7030 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
7031 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
7032 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
7033 desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
7034 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
7035 tmp->setConnectivity(tmp0,tmp1);
7036 tmp->renumberCells(ret0->getConstPointer(),false);
7037 revDesc=tmp->getNodalConnectivity();
7038 revDescIndx=tmp->getNodalConnectivityIndex();
7039 DataArrayInt *ret=0;
7040 if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
7043 ret->getMaxValue(tmp2);
7045 std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
7046 throw INTERP_KERNEL::Exception(oss.str().c_str());
7051 revDescIndx->incrRef();
7054 meshnM1Old2New=ret0;
7059 * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
7060 * necessary for writing the mesh to MED file. Additionally returns a permutation array
7061 * in "Old to New" mode.
7062 * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
7063 * this array using decrRef() as it is no more needed.
7064 * \throw If the nodal connectivity of cells is not defined.
7066 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
7068 checkConnectivityFullyDefined();
7069 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
7070 renumberCells(ret->getConstPointer(),false);
7075 * This methods checks that cells are sorted by their types.
7076 * This method makes asumption (no check) that connectivity is correctly set before calling.
7078 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
7080 checkFullyDefined();
7081 const int *conn=_nodal_connec->getConstPointer();
7082 const int *connI=_nodal_connec_index->getConstPointer();
7083 int nbOfCells=getNumberOfCells();
7084 std::set<INTERP_KERNEL::NormalizedCellType> types;
7085 for(const int *i=connI;i!=connI+nbOfCells;)
7087 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7088 if(types.find(curType)!=types.end())
7090 types.insert(curType);
7091 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7097 * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
7098 * The geometric type order is specified by MED file.
7100 * \sa MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
7102 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
7104 return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7108 * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
7109 * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
7110 * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
7111 * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
7113 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7115 checkFullyDefined();
7116 const int *conn=_nodal_connec->getConstPointer();
7117 const int *connI=_nodal_connec_index->getConstPointer();
7118 int nbOfCells=getNumberOfCells();
7122 std::set<INTERP_KERNEL::NormalizedCellType> sg;
7123 for(const int *i=connI;i!=connI+nbOfCells;)
7125 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7126 const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
7127 if(isTypeExists!=orderEnd)
7129 int pos=(int)std::distance(orderBg,isTypeExists);
7133 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7137 if(sg.find(curType)==sg.end())
7139 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7150 * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
7151 * 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
7152 * 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'.
7154 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
7156 checkConnectivityFullyDefined();
7157 int nbOfCells=getNumberOfCells();
7158 const int *conn=_nodal_connec->getConstPointer();
7159 const int *connI=_nodal_connec_index->getConstPointer();
7160 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
7161 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
7162 tmpa->alloc(nbOfCells,1);
7163 tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
7164 tmpb->fillWithZero();
7165 int *tmp=tmpa->getPointer();
7166 int *tmp2=tmpb->getPointer();
7167 for(const int *i=connI;i!=connI+nbOfCells;i++)
7169 const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
7172 int pos=(int)std::distance(orderBg,where);
7174 tmp[std::distance(connI,i)]=pos;
7178 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
7179 std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
7180 oss << " has a type " << cm.getRepr() << " not in input array of type !";
7181 throw INTERP_KERNEL::Exception(oss.str().c_str());
7184 nbPerType=tmpb.retn();
7189 * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7191 * \return a new object containing the old to new correspondance.
7193 * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7195 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7197 return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7201 * 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.
7202 * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7203 * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7204 * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7206 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7208 DataArrayInt *nbPerType=0;
7209 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7210 nbPerType->decrRef();
7211 return tmpa->buildPermArrPerLevel();
7215 * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7216 * The number of cells remains unchanged after the call of this method.
7217 * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7218 * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7220 * \return the array giving the correspondance old to new.
7222 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7224 checkFullyDefined();
7226 const int *conn=_nodal_connec->getConstPointer();
7227 const int *connI=_nodal_connec_index->getConstPointer();
7228 int nbOfCells=getNumberOfCells();
7229 std::vector<INTERP_KERNEL::NormalizedCellType> types;
7230 for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7231 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7233 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7234 types.push_back(curType);
7235 for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7237 DataArrayInt *ret=DataArrayInt::New();
7238 ret->alloc(nbOfCells,1);
7239 int *retPtr=ret->getPointer();
7240 std::fill(retPtr,retPtr+nbOfCells,-1);
7242 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7244 for(const int *i=connI;i!=connI+nbOfCells;i++)
7245 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7246 retPtr[std::distance(connI,i)]=newCellId++;
7248 renumberCells(retPtr,false);
7253 * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7254 * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7255 * This method makes asumption that connectivity is correctly set before calling.
7257 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7259 checkConnectivityFullyDefined();
7260 const int *conn=_nodal_connec->getConstPointer();
7261 const int *connI=_nodal_connec_index->getConstPointer();
7262 int nbOfCells=getNumberOfCells();
7263 std::vector<MEDCouplingUMesh *> ret;
7264 for(const int *i=connI;i!=connI+nbOfCells;)
7266 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7267 int beginCellId=(int)std::distance(connI,i);
7268 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7269 int endCellId=(int)std::distance(connI,i);
7270 int sz=endCellId-beginCellId;
7271 int *cells=new int[sz];
7272 for(int j=0;j<sz;j++)
7273 cells[j]=beginCellId+j;
7274 MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7282 * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7283 * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7284 * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7286 * \return a newly allocated instance, that the caller must manage.
7287 * \throw If \a this contains more than one geometric type.
7288 * \throw If the nodal connectivity of \a this is not fully defined.
7289 * \throw If the internal data is not coherent.
7291 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7293 checkConnectivityFullyDefined();
7294 if(_types.size()!=1)
7295 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7296 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7297 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7298 ret->setCoords(getCoords());
7299 MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7302 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7303 retC->setNodalConnectivity(c);
7307 MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7309 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7310 DataArrayInt *c=0,*ci=0;
7311 convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7312 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7313 retD->setNodalConnectivity(cs,cis);
7318 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7320 checkConnectivityFullyDefined();
7321 if(_types.size()!=1)
7322 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7323 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7324 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7327 std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7328 oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7329 throw INTERP_KERNEL::Exception(oss.str().c_str());
7331 int nbCells=getNumberOfCells();
7333 int nbNodesPerCell=(int)cm.getNumberOfNodes();
7334 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7335 int *outPtr=connOut->getPointer();
7336 const int *conn=_nodal_connec->begin();
7337 const int *connI=_nodal_connec_index->begin();
7339 for(int i=0;i<nbCells;i++,connI++)
7341 if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7342 outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7345 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 << ") !";
7346 throw INTERP_KERNEL::Exception(oss.str().c_str());
7349 return connOut.retn();
7352 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7354 static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7355 checkConnectivityFullyDefined();
7356 if(_types.size()!=1)
7357 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7358 int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7360 throw INTERP_KERNEL::Exception(msg0);
7361 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7362 c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7363 int *cp(c->getPointer()),*cip(ci->getPointer());
7364 const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7366 for(int i=0;i<nbCells;i++,cip++,incip++)
7368 int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7369 int delta(stop-strt);
7372 if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7373 cp=std::copy(incp+strt,incp+stop,cp);
7375 throw INTERP_KERNEL::Exception(msg0);
7378 throw INTERP_KERNEL::Exception(msg0);
7379 cip[1]=cip[0]+delta;
7381 nodalConn=c.retn(); nodalConnIndex=ci.retn();
7385 * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7386 * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7387 * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7388 * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7389 * are not used here to avoid the build of big permutation array.
7391 * \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
7392 * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7393 * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7394 * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7395 * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7396 * output array gives for each chunck of same type the corresponding mesh id in \b ms.
7397 * \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
7398 * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7400 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7401 DataArrayInt *&szOfCellGrpOfSameType,
7402 DataArrayInt *&idInMsOfCellGrpOfSameType)
7404 std::vector<const MEDCouplingUMesh *> ms2;
7405 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7408 (*it)->checkConnectivityFullyDefined();
7412 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7413 const DataArrayDouble *refCoo=ms2[0]->getCoords();
7414 int meshDim=ms2[0]->getMeshDimension();
7415 std::vector<const MEDCouplingUMesh *> m1ssm;
7416 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7418 std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7419 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7421 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7422 ret1->alloc(0,1); ret2->alloc(0,1);
7423 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7425 if(meshDim!=(*it)->getMeshDimension())
7426 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7427 if(refCoo!=(*it)->getCoords())
7428 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7429 std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7430 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7431 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7432 for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7434 MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7435 m1ssmSingleAuto.push_back(singleCell);
7436 m1ssmSingle.push_back(singleCell);
7437 ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7440 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7441 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7442 std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7443 for(std::size_t i=0;i<m1ssm.size();i++)
7444 m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7445 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7446 szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7447 idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7452 * This method returns a newly created DataArrayInt instance.
7453 * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7455 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7457 checkFullyDefined();
7458 const int *conn=_nodal_connec->getConstPointer();
7459 const int *connIndex=_nodal_connec_index->getConstPointer();
7460 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7461 for(const int *w=begin;w!=end;w++)
7462 if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7463 ret->pushBackSilent(*w);
7468 * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7469 * are in [0:getNumberOfCells())
7471 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7473 checkFullyDefined();
7474 const int *conn=_nodal_connec->getConstPointer();
7475 const int *connI=_nodal_connec_index->getConstPointer();
7476 int nbOfCells=getNumberOfCells();
7477 std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7478 int *tmp=new int[nbOfCells];
7479 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7482 for(const int *i=connI;i!=connI+nbOfCells;i++)
7483 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7484 tmp[std::distance(connI,i)]=j++;
7486 DataArrayInt *ret=DataArrayInt::New();
7487 ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7488 ret->copyStringInfoFrom(*da);
7489 int *retPtr=ret->getPointer();
7490 const int *daPtr=da->getConstPointer();
7491 int nbOfElems=da->getNbOfElems();
7492 for(int k=0;k<nbOfElems;k++)
7493 retPtr[k]=tmp[daPtr[k]];
7499 * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7500 * This method \b works \b for mesh sorted by type.
7501 * cells whose ids is in 'idsPerGeoType' array.
7502 * This method conserves coords and name of mesh.
7504 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7506 std::vector<int> code=getDistributionOfTypes();
7507 std::size_t nOfTypesInThis=code.size()/3;
7508 int sz=0,szOfType=0;
7509 for(std::size_t i=0;i<nOfTypesInThis;i++)
7514 szOfType=code[3*i+1];
7516 for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7517 if(*work<0 || *work>=szOfType)
7519 std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7520 oss << ". It should be in [0," << szOfType << ") !";
7521 throw INTERP_KERNEL::Exception(oss.str().c_str());
7523 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7524 int *idsPtr=idsTokeep->getPointer();
7526 for(std::size_t i=0;i<nOfTypesInThis;i++)
7529 for(int j=0;j<code[3*i+1];j++)
7532 idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7533 offset+=code[3*i+1];
7535 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7536 ret->copyTinyInfoFrom(this);
7541 * This method returns a vector of size 'this->getNumberOfCells()'.
7542 * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7544 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7546 int ncell=getNumberOfCells();
7547 std::vector<bool> ret(ncell);
7548 const int *cI=getNodalConnectivityIndex()->getConstPointer();
7549 const int *c=getNodalConnectivity()->getConstPointer();
7550 for(int i=0;i<ncell;i++)
7552 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7553 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7554 ret[i]=cm.isQuadratic();
7560 * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7562 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7564 if(other->getType()!=UNSTRUCTURED)
7565 throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7566 const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7567 return MergeUMeshes(this,otherC);
7571 * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7572 * computed by averaging coordinates of cell nodes, so this method is not a right
7573 * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7574 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7575 * this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7576 * components. The caller is to delete this array using decrRef() as it is
7578 * \throw If the coordinates array is not set.
7579 * \throw If the nodal connectivity of cells is not defined.
7580 * \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7582 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7584 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7585 int spaceDim=getSpaceDimension();
7586 int nbOfCells=getNumberOfCells();
7587 ret->alloc(nbOfCells,spaceDim);
7588 ret->copyStringInfoFrom(*getCoords());
7589 double *ptToFill=ret->getPointer();
7590 const int *nodal=_nodal_connec->getConstPointer();
7591 const int *nodalI=_nodal_connec_index->getConstPointer();
7592 const double *coor=_coords->getConstPointer();
7593 for(int i=0;i<nbOfCells;i++)
7595 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7596 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7603 * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7604 * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the
7606 * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned
7607 * DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7609 * \sa MEDCouplingUMesh::getBarycenterAndOwner
7610 * \throw If \a this is not fully defined (coordinates and connectivity)
7611 * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7613 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7615 checkFullyDefined();
7616 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7617 int spaceDim=getSpaceDimension();
7618 int nbOfCells=getNumberOfCells();
7619 int nbOfNodes=getNumberOfNodes();
7620 ret->alloc(nbOfCells,spaceDim);
7621 double *ptToFill=ret->getPointer();
7622 const int *nodal=_nodal_connec->getConstPointer();
7623 const int *nodalI=_nodal_connec_index->getConstPointer();
7624 const double *coor=_coords->getConstPointer();
7625 for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7627 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7628 std::fill(ptToFill,ptToFill+spaceDim,0.);
7629 if(type!=INTERP_KERNEL::NORM_POLYHED)
7631 for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7633 if(*conn>=0 && *conn<nbOfNodes)
7634 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7637 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," << nbOfNodes << ") !";
7638 throw INTERP_KERNEL::Exception(oss.str().c_str());
7641 int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7642 if(nbOfNodesInCell>0)
7643 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7646 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7647 throw INTERP_KERNEL::Exception(oss.str().c_str());
7652 std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7654 for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7656 if(*it>=0 && *it<nbOfNodes)
7657 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7660 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," << nbOfNodes << ") !";
7661 throw INTERP_KERNEL::Exception(oss.str().c_str());
7665 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7668 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7669 throw INTERP_KERNEL::Exception(oss.str().c_str());
7677 * Returns a new DataArrayDouble holding barycenters of specified cells. The
7678 * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7679 * are specified via an array of cell ids.
7680 * \warning Validity of the specified cell ids is not checked!
7681 * Valid range is [ 0, \a this->getNumberOfCells() ).
7682 * \param [in] begin - an array of cell ids of interest.
7683 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7684 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7685 * end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7686 * caller is to delete this array using decrRef() as it is no more needed.
7687 * \throw If the coordinates array is not set.
7688 * \throw If the nodal connectivity of cells is not defined.
7690 * \if ENABLE_EXAMPLES
7691 * \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7692 * \ref py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7695 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7697 DataArrayDouble *ret=DataArrayDouble::New();
7698 int spaceDim=getSpaceDimension();
7699 int nbOfTuple=(int)std::distance(begin,end);
7700 ret->alloc(nbOfTuple,spaceDim);
7701 double *ptToFill=ret->getPointer();
7702 double *tmp=new double[spaceDim];
7703 const int *nodal=_nodal_connec->getConstPointer();
7704 const int *nodalI=_nodal_connec_index->getConstPointer();
7705 const double *coor=_coords->getConstPointer();
7706 for(const int *w=begin;w!=end;w++)
7708 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7709 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7717 * 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".
7718 * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7719 * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7720 * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7721 * This method is useful to detect 2D cells in 3D space that are not coplanar.
7723 * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7724 * \throw If spaceDim!=3 or meshDim!=2.
7725 * \throw If connectivity of \a this is invalid.
7726 * \throw If connectivity of a cell in \a this points to an invalid node.
7728 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7730 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7731 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7732 if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7733 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7734 ret->alloc(nbOfCells,4);
7735 double *retPtr(ret->getPointer());
7736 const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7737 const double *coor(_coords->begin());
7738 for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7740 double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7741 if(nodalI[1]-nodalI[0]>=3)
7743 for(int j=0;j<3;j++)
7745 int nodeId(nodal[nodalI[0]+1+j]);
7746 if(nodeId>=0 && nodeId<nbOfNodes)
7747 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7750 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7751 throw INTERP_KERNEL::Exception(oss.str().c_str());
7757 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7758 throw INTERP_KERNEL::Exception(oss.str().c_str());
7760 INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7761 retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7767 * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7770 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7773 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7774 da->checkAllocated();
7775 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7777 int nbOfTuples=da->getNumberOfTuples();
7778 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7779 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7780 c->alloc(2*nbOfTuples,1);
7781 cI->alloc(nbOfTuples+1,1);
7782 int *cp=c->getPointer();
7783 int *cip=cI->getPointer();
7785 for(int i=0;i<nbOfTuples;i++)
7787 *cp++=INTERP_KERNEL::NORM_POINT1;
7791 ret->setConnectivity(c,cI,true);
7795 * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7796 * Cells and nodes of
7797 * the first mesh precede cells and nodes of the second mesh within the result mesh.
7798 * \param [in] mesh1 - the first mesh.
7799 * \param [in] mesh2 - the second mesh.
7800 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7801 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7802 * is no more needed.
7803 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7804 * \throw If the coordinates array is not set in none of the meshes.
7805 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7806 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7808 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7810 std::vector<const MEDCouplingUMesh *> tmp(2);
7811 tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7812 return MergeUMeshes(tmp);
7816 * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7817 * Cells and nodes of
7818 * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7819 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7820 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7821 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7822 * is no more needed.
7823 * \throw If \a a.size() == 0.
7824 * \throw If \a a[ *i* ] == NULL.
7825 * \throw If the coordinates array is not set in none of the meshes.
7826 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7827 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7829 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7831 std::size_t sz=a.size();
7833 return MergeUMeshesLL(a);
7834 for(std::size_t ii=0;ii<sz;ii++)
7837 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7838 throw INTERP_KERNEL::Exception(oss.str().c_str());
7840 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7841 std::vector< const MEDCouplingUMesh * > aa(sz);
7843 for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7845 const MEDCouplingUMesh *cur=a[i];
7846 const DataArrayDouble *coo=cur->getCoords();
7848 spaceDim=coo->getNumberOfComponents();
7851 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7852 for(std::size_t i=0;i<sz;i++)
7854 bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7857 return MergeUMeshesLL(aa);
7862 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7865 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7866 std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7867 int meshDim=(*it)->getMeshDimension();
7868 int nbOfCells=(*it)->getNumberOfCells();
7869 int meshLgth=(*it++)->getMeshLength();
7870 for(;it!=a.end();it++)
7872 if(meshDim!=(*it)->getMeshDimension())
7873 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7874 nbOfCells+=(*it)->getNumberOfCells();
7875 meshLgth+=(*it)->getMeshLength();
7877 std::vector<const MEDCouplingPointSet *> aps(a.size());
7878 std::copy(a.begin(),a.end(),aps.begin());
7879 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7880 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7881 ret->setCoords(pts);
7882 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7883 c->alloc(meshLgth,1);
7884 int *cPtr=c->getPointer();
7885 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7886 cI->alloc(nbOfCells+1,1);
7887 int *cIPtr=cI->getPointer();
7891 for(it=a.begin();it!=a.end();it++)
7893 int curNbOfCell=(*it)->getNumberOfCells();
7894 const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7895 const int *curC=(*it)->_nodal_connec->getConstPointer();
7896 cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7897 for(int j=0;j<curNbOfCell;j++)
7899 const int *src=curC+curCI[j];
7901 for(;src!=curC+curCI[j+1];src++,cPtr++)
7909 offset+=curCI[curNbOfCell];
7910 offset2+=(*it)->getNumberOfNodes();
7913 ret->setConnectivity(c,cI,true);
7920 * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7921 * dimension and sharing the node coordinates array.
7922 * All cells of the first mesh precede all cells of the second mesh
7923 * within the result mesh.
7924 * \param [in] mesh1 - the first mesh.
7925 * \param [in] mesh2 - the second mesh.
7926 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7927 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7928 * is no more needed.
7929 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7930 * \throw If the meshes do not share the node coordinates array.
7931 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7932 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7934 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7936 std::vector<const MEDCouplingUMesh *> tmp(2);
7937 tmp[0]=mesh1; tmp[1]=mesh2;
7938 return MergeUMeshesOnSameCoords(tmp);
7942 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7943 * dimension and sharing the node coordinates array.
7944 * All cells of the *i*-th mesh precede all cells of the
7945 * (*i*+1)-th mesh within the result mesh.
7946 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7947 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7948 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7949 * is no more needed.
7950 * \throw If \a a.size() == 0.
7951 * \throw If \a a[ *i* ] == NULL.
7952 * \throw If the meshes do not share the node coordinates array.
7953 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7954 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7956 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7959 throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7960 for(std::size_t ii=0;ii<meshes.size();ii++)
7963 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7964 throw INTERP_KERNEL::Exception(oss.str().c_str());
7966 const DataArrayDouble *coords=meshes.front()->getCoords();
7967 int meshDim=meshes.front()->getMeshDimension();
7968 std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7970 int meshIndexLgth=0;
7971 for(;iter!=meshes.end();iter++)
7973 if(coords!=(*iter)->getCoords())
7974 throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7975 if(meshDim!=(*iter)->getMeshDimension())
7976 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7977 meshLgth+=(*iter)->getMeshLength();
7978 meshIndexLgth+=(*iter)->getNumberOfCells();
7980 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7981 nodal->alloc(meshLgth,1);
7982 int *nodalPtr=nodal->getPointer();
7983 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7984 nodalIndex->alloc(meshIndexLgth+1,1);
7985 int *nodalIndexPtr=nodalIndex->getPointer();
7987 for(iter=meshes.begin();iter!=meshes.end();iter++)
7989 const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7990 const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7991 int nbOfCells=(*iter)->getNumberOfCells();
7992 int meshLgth2=(*iter)->getMeshLength();
7993 nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7994 if(iter!=meshes.begin())
7995 nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7997 nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
8000 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
8001 ret->setName("merge");
8002 ret->setMeshDimension(meshDim);
8003 ret->setConnectivity(nodal,nodalIndex,true);
8004 ret->setCoords(coords);
8009 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
8010 * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
8011 * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
8012 * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
8013 * New" mode are returned for each input mesh.
8014 * \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
8015 * \param [in] compType - specifies a cell comparison technique. For meaning of its
8016 * valid values [0,1,2], see zipConnectivityTraducer().
8017 * \param [in,out] corr - an array of DataArrayInt, of the same size as \a
8018 * meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
8019 * mesh. The caller is to delete each of the arrays using decrRef() as it is
8021 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
8022 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8023 * is no more needed.
8024 * \throw If \a meshes.size() == 0.
8025 * \throw If \a meshes[ *i* ] == NULL.
8026 * \throw If the meshes do not share the node coordinates array.
8027 * \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
8028 * \throw If the \a meshes are of different dimension (getMeshDimension()).
8029 * \throw If the nodal connectivity of cells of any of \a meshes is not defined.
8030 * \throw If the nodal connectivity any of \a meshes includes an invalid id.
8032 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
8034 //All checks are delegated to MergeUMeshesOnSameCoords
8035 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
8036 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
8037 corr.resize(meshes.size());
8038 std::size_t nbOfMeshes=meshes.size();
8040 const int *o2nPtr=o2n->getConstPointer();
8041 for(std::size_t i=0;i<nbOfMeshes;i++)
8043 DataArrayInt *tmp=DataArrayInt::New();
8044 int curNbOfCells=meshes[i]->getNumberOfCells();
8045 tmp->alloc(curNbOfCells,1);
8046 std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
8047 offset+=curNbOfCells;
8048 tmp->setName(meshes[i]->getName());
8055 * Makes all given meshes share the nodal connectivity array. The common connectivity
8056 * array is created by concatenating the connectivity arrays of all given meshes. All
8057 * the given meshes must be of the same space dimension but dimension of cells **can
8058 * differ**. This method is particulary useful in MEDLoader context to build a \ref
8059 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8060 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8061 * \param [in,out] meshes - a vector of meshes to update.
8062 * \throw If any of \a meshes is NULL.
8063 * \throw If the coordinates array is not set in any of \a meshes.
8064 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8065 * \throw If \a meshes are of different space dimension.
8067 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
8069 std::size_t sz=meshes.size();
8072 std::vector< const DataArrayDouble * > coords(meshes.size());
8073 std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
8074 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
8078 (*it)->checkConnectivityFullyDefined();
8079 const DataArrayDouble *coo=(*it)->getCoords();
8084 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8085 oss << " has no coordinate array defined !";
8086 throw INTERP_KERNEL::Exception(oss.str().c_str());
8091 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8092 oss << " is null !";
8093 throw INTERP_KERNEL::Exception(oss.str().c_str());
8096 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
8097 std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
8098 int offset=(*it)->getNumberOfNodes();
8099 (*it++)->setCoords(res);
8100 for(;it!=meshes.end();it++)
8102 int oldNumberOfNodes=(*it)->getNumberOfNodes();
8103 (*it)->setCoords(res);
8104 (*it)->shiftNodeNumbersInConn(offset);
8105 offset+=oldNumberOfNodes;
8110 * Merges nodes coincident with a given precision within all given meshes that share
8111 * the nodal connectivity array. The given meshes **can be of different** mesh
8112 * dimension. This method is particulary useful in MEDLoader context to build a \ref
8113 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8114 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8115 * \param [in,out] meshes - a vector of meshes to update.
8116 * \param [in] eps - the precision used to detect coincident nodes (infinite norm).
8117 * \throw If any of \a meshes is NULL.
8118 * \throw If the \a meshes do not share the same node coordinates array.
8119 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8121 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
8125 std::set<const DataArrayDouble *> s;
8126 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8129 s.insert((*it)->getCoords());
8132 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 !";
8133 throw INTERP_KERNEL::Exception(oss.str().c_str());
8138 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 !";
8139 throw INTERP_KERNEL::Exception(oss.str().c_str());
8141 const DataArrayDouble *coo=*(s.begin());
8145 DataArrayInt *comm,*commI;
8146 coo->findCommonTuples(eps,-1,comm,commI);
8147 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
8148 int oldNbOfNodes=coo->getNumberOfTuples();
8150 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
8151 if(oldNbOfNodes==newNbOfNodes)
8153 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
8154 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8156 (*it)->renumberNodesInConn(o2n->getConstPointer());
8157 (*it)->setCoords(newCoords);
8162 * 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.
8163 * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
8164 * \param isQuad specifies the policy of connectivity.
8165 * @ret in/out parameter in which the result will be append
8167 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
8169 INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
8170 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
8171 ret.push_back(cm.getExtrudedType());
8172 int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
8175 case INTERP_KERNEL::NORM_POINT1:
8177 ret.push_back(connBg[1]);
8178 ret.push_back(connBg[1]+nbOfNodesPerLev);
8181 case INTERP_KERNEL::NORM_SEG2:
8183 int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
8184 ret.insert(ret.end(),conn,conn+4);
8187 case INTERP_KERNEL::NORM_SEG3:
8189 int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8190 ret.insert(ret.end(),conn,conn+8);
8193 case INTERP_KERNEL::NORM_QUAD4:
8195 int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8196 ret.insert(ret.end(),conn,conn+8);
8199 case INTERP_KERNEL::NORM_TRI3:
8201 int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8202 ret.insert(ret.end(),conn,conn+6);
8205 case INTERP_KERNEL::NORM_TRI6:
8207 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,
8208 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8209 ret.insert(ret.end(),conn,conn+15);
8212 case INTERP_KERNEL::NORM_QUAD8:
8215 connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8216 connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8217 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8219 ret.insert(ret.end(),conn,conn+20);
8222 case INTERP_KERNEL::NORM_POLYGON:
8224 std::back_insert_iterator< std::vector<int> > ii(ret);
8225 std::copy(connBg+1,connEnd,ii);
8227 std::reverse_iterator<const int *> rConnBg(connEnd);
8228 std::reverse_iterator<const int *> rConnEnd(connBg+1);
8229 std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8230 std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8231 for(std::size_t i=0;i<nbOfRadFaces;i++)
8234 int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8235 std::copy(conn,conn+4,ii);
8240 throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8245 * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8247 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8250 double v[3]={0.,0.,0.};
8251 std::size_t sz=std::distance(begin,end);
8256 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];
8257 v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8258 v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8260 double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8262 // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8263 // SEG3 forming a circle):
8264 if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8266 v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8267 for(std::size_t j=0;j<sz;j++)
8269 if (j%2) // current point i is quadratic, next point i+1 is standard
8272 ip1 = (j+1)%sz; // ip1 = "i+1"
8274 else // current point i is standard, next point i+1 is quadratic
8279 v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8280 v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8281 v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8283 ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8289 * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8291 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8293 std::vector<std::pair<int,int> > edges;
8294 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8295 const int *bgFace=begin;
8296 for(std::size_t i=0;i<nbOfFaces;i++)
8298 const int *endFace=std::find(bgFace+1,end,-1);
8299 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8300 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8302 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8303 if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8305 edges.push_back(p1);
8309 return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8313 * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8315 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8317 double vec0[3],vec1[3];
8318 std::size_t sz=std::distance(begin,end);
8320 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8321 int nbOfNodes=(int)sz/2;
8322 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8323 const double *pt0=coords+3*begin[0];
8324 const double *pt1=coords+3*begin[nbOfNodes];
8325 vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8326 return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8329 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8331 std::size_t sz=std::distance(begin,end);
8332 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8333 std::size_t nbOfNodes(sz/2);
8334 std::copy(begin,end,(int *)tmp);
8335 for(std::size_t j=1;j<nbOfNodes;j++)
8337 begin[j]=tmp[nbOfNodes-j];
8338 begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8342 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8344 std::size_t sz=std::distance(begin,end);
8346 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8347 double vec0[3],vec1[3];
8348 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8349 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];
8350 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;
8353 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8355 std::size_t sz=std::distance(begin,end);
8357 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8359 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8360 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8361 return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8365 * 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 )
8366 * 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
8369 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8370 * \param [in] coords the coordinates with nb of components exactly equal to 3
8371 * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8372 * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8373 * \param [out] res the result is put at the end of the vector without any alteration of the data.
8375 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8377 int nbFaces=std::count(begin+1,end,-1)+1;
8378 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8379 double *vPtr=v->getPointer();
8380 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8381 double *pPtr=p->getPointer();
8382 const int *stFaceConn=begin+1;
8383 for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8385 const int *endFaceConn=std::find(stFaceConn,end,-1);
8386 ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8387 stFaceConn=endFaceConn+1;
8389 pPtr=p->getPointer(); vPtr=v->getPointer();
8390 DataArrayInt *comm1=0,*commI1=0;
8391 v->findCommonTuples(eps,-1,comm1,commI1);
8392 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8393 const int *comm1Ptr=comm1->getConstPointer();
8394 const int *commI1Ptr=commI1->getConstPointer();
8395 int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8396 res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8398 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8399 mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8400 mm->finishInsertingCells();
8402 for(int i=0;i<nbOfGrps1;i++)
8404 int vecId=comm1Ptr[commI1Ptr[i]];
8405 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8406 DataArrayInt *comm2=0,*commI2=0;
8407 tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8408 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8409 const int *comm2Ptr=comm2->getConstPointer();
8410 const int *commI2Ptr=commI2->getConstPointer();
8411 int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8412 for(int j=0;j<nbOfGrps2;j++)
8414 if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8416 res->insertAtTheEnd(begin,end);
8417 res->pushBackSilent(-1);
8421 int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8422 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8423 ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8424 DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8425 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8426 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8427 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8428 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8429 const int *idsNodePtr=idsNode->getConstPointer();
8430 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];
8431 double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8432 double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8433 if(std::abs(norm)>eps)
8435 double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8436 mm3->rotate(center,vec,angle);
8438 mm3->changeSpaceDimension(2);
8439 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8440 const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8441 const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8442 int nbOfCells=mm4->getNumberOfCells();
8443 for(int k=0;k<nbOfCells;k++)
8446 for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8447 res->pushBackSilent(idsNodePtr[*work]);
8448 res->pushBackSilent(-1);
8453 res->popBackSilent();
8457 * 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
8458 * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8460 * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8461 * \param [in] coords coordinates expected to have 3 components.
8462 * \param [in] begin start of the nodal connectivity of the face.
8463 * \param [in] end end of the nodal connectivity (excluded) of the face.
8464 * \param [out] v the normalized vector of size 3
8465 * \param [out] p the pos of plane
8467 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8469 std::size_t nbPoints=std::distance(begin,end);
8471 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8472 double vec[3]={0.,0.,0.};
8474 bool refFound=false;
8475 for(;j<nbPoints-1 && !refFound;j++)
8477 vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8478 vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8479 vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8480 double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8484 vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8487 for(std::size_t i=j;i<nbPoints-1;i++)
8490 curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8491 curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8492 curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8493 double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8496 curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8497 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];
8498 norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8501 v[0]/=norm; v[1]/=norm; v[2]/=norm;
8502 *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8506 throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8510 * This method tries to obtain a well oriented polyhedron.
8511 * If the algorithm fails, an exception will be thrown.
8513 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8515 std::list< std::pair<int,int> > edgesOK,edgesFinished;
8516 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8517 std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8519 int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8520 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8521 for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8523 while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8526 std::size_t smthChanged=0;
8527 for(std::size_t i=0;i<nbOfFaces;i++)
8529 endFace=std::find(bgFace+1,end,-1);
8530 nbOfEdgesInFace=std::distance(bgFace,endFace);
8534 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8536 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8537 std::pair<int,int> p2(p1.second,p1.first);
8538 bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8539 bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8540 if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8545 std::reverse(bgFace+1,endFace);
8546 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8548 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8549 std::pair<int,int> p2(p1.second,p1.first);
8550 if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8551 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8552 if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8553 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8554 std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8555 if(it!=edgesOK.end())
8558 edgesFinished.push_back(p1);
8561 edgesOK.push_back(p1);
8568 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8570 if(!edgesOK.empty())
8571 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8572 if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8573 {//not lucky ! The first face was not correctly oriented : reorient all faces...
8575 for(std::size_t i=0;i<nbOfFaces;i++)
8577 endFace=std::find(bgFace+1,end,-1);
8578 std::reverse(bgFace+1,endFace);
8584 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8586 int nbOfNodesExpected(skin->getNumberOfNodes());
8587 const int *n2oPtr(n2o->getConstPointer());
8588 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8589 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8590 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8591 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8592 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8593 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8594 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_POLYGON;
8595 if(nbOfNodesExpected<1)
8597 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8598 *work++=n2oPtr[prevNode];
8599 for(int i=1;i<nbOfNodesExpected;i++)
8601 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8603 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8604 conn.erase(prevNode);
8607 int curNode(*(conn.begin()));
8608 *work++=n2oPtr[curNode];
8609 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8610 shar.erase(prevCell);
8613 prevCell=*(shar.begin());
8617 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8620 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8623 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8628 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8630 int nbOfNodesExpected(skin->getNumberOfNodes());
8631 int nbOfTurn(nbOfNodesExpected/2);
8632 const int *n2oPtr(n2o->getConstPointer());
8633 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8634 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8635 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8636 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8637 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8638 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8639 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_QPOLYG;
8640 if(nbOfNodesExpected<1)
8642 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8643 *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8644 for(int i=1;i<nbOfTurn;i++)
8646 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8648 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8649 conn.erase(prevNode);
8652 int curNode(*(conn.begin()));
8653 *work=n2oPtr[curNode];
8654 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8655 shar.erase(prevCell);
8658 int curCell(*(shar.begin()));
8659 work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8665 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8668 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8671 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8677 * This method makes the assumption spacedimension == meshdimension == 2.
8678 * This method works only for linear cells.
8680 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8682 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8684 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8685 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8686 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8687 int oldNbOfNodes(skin->getNumberOfNodes());
8688 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8689 int nbOfNodesExpected(skin->getNumberOfNodes());
8690 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8691 int nbCells(skin->getNumberOfCells());
8692 if(nbCells==nbOfNodesExpected)
8693 return buildUnionOf2DMeshLinear(skin,n2o);
8694 else if(2*nbCells==nbOfNodesExpected)
8695 return buildUnionOf2DMeshQuadratic(skin,n2o);
8697 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8701 * This method makes the assumption spacedimension == meshdimension == 3.
8702 * This method works only for linear cells.
8704 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8706 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8708 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8709 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8710 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8711 const int *conn=m->getNodalConnectivity()->getConstPointer();
8712 const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8713 int nbOfCells=m->getNumberOfCells();
8714 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8715 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED;
8718 work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8719 for(int i=1;i<nbOfCells;i++)
8722 work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8728 * \brief Creates a graph of cell neighbors
8729 * \return MEDCouplingSkyLineArray * - an sky line array the user should delete.
8730 * In the sky line array, graph arcs are stored in terms of (index,value) notation.
8732 * - index: 0 3 5 6 6
8733 * - value: 1 2 3 2 3 3
8734 * means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8735 * Arcs are not doubled but reflexive (1,1) arcs are present for each cell
8737 MEDCouplingSkyLineArray *MEDCouplingUMesh::generateGraph() const
8739 checkConnectivityFullyDefined();
8741 int meshDim = this->getMeshDimension();
8742 ParaMEDMEM::DataArrayInt* indexr=ParaMEDMEM::DataArrayInt::New();
8743 ParaMEDMEM::DataArrayInt* revConn=ParaMEDMEM::DataArrayInt::New();
8744 this->getReverseNodalConnectivity(revConn,indexr);
8745 const int* indexr_ptr=indexr->getConstPointer();
8746 const int* revConn_ptr=revConn->getConstPointer();
8748 const ParaMEDMEM::DataArrayInt* index;
8749 const ParaMEDMEM::DataArrayInt* conn;
8750 conn=this->getNodalConnectivity(); // it includes a type as the 1st element!!!
8751 index=this->getNodalConnectivityIndex();
8752 int nbCells=this->getNumberOfCells();
8753 const int* index_ptr=index->getConstPointer();
8754 const int* conn_ptr=conn->getConstPointer();
8756 //creating graph arcs (cell to cell relations)
8757 //arcs are stored in terms of (index,value) notation
8760 // means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8761 // in present version arcs are not doubled but reflexive (1,1) arcs are present for each cell
8763 //warning here one node have less than or equal effective number of cell with it
8764 //but cell could have more than effective nodes
8765 //because other equals nodes in other domain (with other global inode)
8766 std::vector <int> cell2cell_index(nbCells+1,0);
8767 std::vector <int> cell2cell;
8768 cell2cell.reserve(3*nbCells);
8770 for (int icell=0; icell<nbCells;icell++)
8772 std::map<int,int > counter;
8773 for (int iconn=index_ptr[icell]+1; iconn<index_ptr[icell+1];iconn++)
8775 int inode=conn_ptr[iconn];
8776 for (int iconnr=indexr_ptr[inode]; iconnr<indexr_ptr[inode+1];iconnr++)
8778 int icell2=revConn_ptr[iconnr];
8779 std::map<int,int>::iterator iter=counter.find(icell2);
8780 if (iter!=counter.end()) (iter->second)++;
8781 else counter.insert(std::make_pair(icell2,1));
8784 for (std::map<int,int>::const_iterator iter=counter.begin();
8785 iter!=counter.end(); iter++)
8786 if (iter->second >= meshDim)
8788 cell2cell_index[icell+1]++;
8789 cell2cell.push_back(iter->first);
8794 cell2cell_index[0]=0;
8795 for (int icell=0; icell<nbCells;icell++)
8796 cell2cell_index[icell+1]=cell2cell_index[icell]+cell2cell_index[icell+1];
8798 //filling up index and value to create skylinearray structure
8799 MEDCouplingSkyLineArray* array=new MEDCouplingSkyLineArray(cell2cell_index,cell2cell);
8804 * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8805 * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8807 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8811 for(int i=0;i<nbOfNodesInCell;i++)
8812 w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8813 else if(spaceDim==2)
8815 for(int i=0;i<nbOfNodesInCell;i++)
8817 w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8822 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8825 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8827 int nbOfCells=getNumberOfCells();
8829 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8830 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};
8831 ofs << " <" << getVTKDataSetType() << ">\n";
8832 ofs << " <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8833 ofs << " <PointData>\n" << pointData << std::endl;
8834 ofs << " </PointData>\n";
8835 ofs << " <CellData>\n" << cellData << std::endl;
8836 ofs << " </CellData>\n";
8837 ofs << " <Points>\n";
8838 if(getSpaceDimension()==3)
8839 _coords->writeVTK(ofs,8,"Points",byteData);
8842 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8843 coo->writeVTK(ofs,8,"Points",byteData);
8845 ofs << " </Points>\n";
8846 ofs << " <Cells>\n";
8847 const int *cPtr=_nodal_connec->getConstPointer();
8848 const int *cIPtr=_nodal_connec_index->getConstPointer();
8849 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8850 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8851 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8852 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8853 int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8854 int szFaceOffsets=0,szConn=0;
8855 for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8858 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8861 *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8862 w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8866 int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8867 *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8868 std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8869 *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8870 w4=std::copy(c.begin(),c.end(),w4);
8873 types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8874 types->writeVTK(ofs,8,"UInt8","types",byteData);
8875 offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8876 if(szFaceOffsets!=0)
8877 {//presence of Polyhedra
8878 connectivity->reAlloc(szConn);
8879 faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8880 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8881 w1=faces->getPointer();
8882 for(int i=0;i<nbOfCells;i++)
8883 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8885 int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8887 const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8888 for(int j=0;j<nbFaces;j++)
8890 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8891 *w1++=(int)std::distance(w6,w5);
8892 w1=std::copy(w6,w5,w1);
8896 faces->writeVTK(ofs,8,"Int32","faces",byteData);
8898 connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8899 ofs << " </Cells>\n";
8900 ofs << " </Piece>\n";
8901 ofs << " </" << getVTKDataSetType() << ">\n";
8904 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8906 stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8908 { stream << " Not set !"; return ; }
8909 stream << " Mesh dimension : " << _mesh_dim << ".";
8913 { stream << " No coordinates set !"; return ; }
8914 if(!_coords->isAllocated())
8915 { stream << " Coordinates set but not allocated !"; return ; }
8916 stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8917 stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8918 if(!_nodal_connec_index)
8919 { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8920 if(!_nodal_connec_index->isAllocated())
8921 { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8922 int lgth=_nodal_connec_index->getNumberOfTuples();
8923 int cpt=_nodal_connec_index->getNumberOfComponents();
8924 if(cpt!=1 || lgth<1)
8926 stream << std::endl << "Number of cells : " << lgth-1 << ".";
8929 std::string MEDCouplingUMesh::getVTKDataSetType() const
8931 return std::string("UnstructuredGrid");
8934 std::string MEDCouplingUMesh::getVTKFileExtension() const
8936 return std::string("vtu");
8940 * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8941 * returns a result mesh constituted by polygons.
8942 * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8943 * all nodes from m2.
8944 * The meshes should be in 2D space. In
8945 * addition, returns two arrays mapping cells of the result mesh to cells of the input
8947 * \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
8948 * 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)
8949 * \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
8950 * 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)
8951 * \param [in] eps - precision used to detect coincident mesh entities.
8952 * \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8953 * cell an id of the cell of \a m1 it comes from. The caller is to delete
8954 * this array using decrRef() as it is no more needed.
8955 * \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8956 * cell an id of the cell of \a m2 it comes from. -1 value means that a
8957 * result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8958 * any cell of \a m2. The caller is to delete this array using decrRef() as
8959 * it is no more needed.
8960 * \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8961 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8962 * is no more needed.
8963 * \throw If the coordinates array is not set in any of the meshes.
8964 * \throw If the nodal connectivity of cells is not defined in any of the meshes.
8965 * \throw If any of the meshes is not a 2D mesh in 2D space.
8967 * \sa conformize2D, mergeNodes
8969 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8970 double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8973 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
8974 m1->checkFullyDefined();
8975 m2->checkFullyDefined();
8976 if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8977 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!");
8979 // Step 1: compute all edge intersections (new nodes)
8980 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8981 MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
8982 DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8983 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
8984 IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
8985 m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8986 addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
8987 revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8988 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8989 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8991 // Step 2: re-order newly created nodes according to the ordering found in m2
8992 std::vector< std::vector<int> > intersectEdge2;
8993 BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8994 subDiv2.clear(); dd5=0; dd6=0;
8997 std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8998 std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8999 BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
9000 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
9002 // Step 4: Prepare final result:
9003 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9004 addCooDa->alloc((int)(addCoo.size())/2,2);
9005 std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
9006 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
9007 addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
9008 std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
9009 std::vector<const DataArrayDouble *> coordss(4);
9010 coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
9011 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
9012 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
9013 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
9014 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
9015 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
9016 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
9017 ret->setConnectivity(conn,connI,true);
9018 ret->setCoords(coo);
9019 cellNb1=c1.retn(); cellNb2=c2.retn();
9025 bool IsColinearOfACellOf(const std::vector< std::vector<int> >& intersectEdge1, const std::vector<int>& candidates, int start, int stop, int& retVal)
9027 if(candidates.empty())
9029 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
9031 const std::vector<int>& pool(intersectEdge1[*it]);
9032 int tmp[2]; tmp[0]=start; tmp[1]=stop;
9033 if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9038 tmp[0]=stop; tmp[1]=start;
9039 if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9048 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,
9049 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInRetColinear, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInMesh1DForIdsInRetColinear)
9051 idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1);
9052 idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1);
9053 int nCells(mesh1D->getNumberOfCells());
9054 if(nCells!=(int)intersectEdge2.size())
9055 throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
9056 const DataArrayDouble *coo2(mesh1D->getCoords());
9057 const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
9058 const double *coo2Ptr(coo2->begin());
9059 int offset1(coords1->getNumberOfTuples());
9060 int offset2(offset1+coo2->getNumberOfTuples());
9061 int offset3(offset2+addCoo.size()/2);
9062 std::vector<double> addCooQuad;
9063 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
9064 int tmp[4],cicnt(0),kk(0);
9065 for(int i=0;i<nCells;i++)
9067 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9068 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
9069 const std::vector<int>& subEdges(intersectEdge2[i]);
9070 int nbSubEdge(subEdges.size()/2);
9071 for(int j=0;j<nbSubEdge;j++,kk++)
9073 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));
9074 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
9075 INTERP_KERNEL::Edge *e2Ptr(e2);
9076 std::map<int,int>::const_iterator itm;
9077 if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
9079 tmp[0]=INTERP_KERNEL::NORM_SEG3;
9080 itm=mergedNodes.find(subEdges[2*j]);
9081 tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9082 itm=mergedNodes.find(subEdges[2*j+1]);
9083 tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9084 tmp[3]=offset3+(int)addCooQuad.size()/2;
9086 e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2);
9088 cOut->insertAtTheEnd(tmp,tmp+4);
9089 ciOut->pushBackSilent(cicnt);
9093 tmp[0]=INTERP_KERNEL::NORM_SEG2;
9094 itm=mergedNodes.find(subEdges[2*j]);
9095 tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9096 itm=mergedNodes.find(subEdges[2*j+1]);
9097 tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9099 cOut->insertAtTheEnd(tmp,tmp+3);
9100 ciOut->pushBackSilent(cicnt);
9103 if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00))
9105 idsInRetColinear->pushBackSilent(kk);
9106 idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00);
9111 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
9112 ret->setConnectivity(cOut,ciOut,true);
9113 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr3(DataArrayDouble::New());
9114 arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9115 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
9116 std::vector<const DataArrayDouble *> coordss(4);
9117 coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
9118 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
9119 ret->setCoords(arr);
9123 MEDCouplingUMesh *BuildRefined2DCellLinear(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9125 std::vector<int> allEdges;
9126 for(const int *it2(descBg);it2!=descEnd;it2++)
9128 const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9130 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9132 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9134 std::size_t nb(allEdges.size());
9136 throw INTERP_KERNEL::Exception("BuildRefined2DCellLinear : internal error 1 !");
9137 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9138 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9139 ret->setCoords(coords);
9140 ret->allocateCells(1);
9141 std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9142 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9143 connOut[kk]=allEdges[2*kk];
9144 ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]);
9148 MEDCouplingUMesh *BuildRefined2DCellQuadratic(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9150 const int *c(mesh2D->getNodalConnectivity()->begin()),*ci(mesh2D->getNodalConnectivityIndex()->begin());
9151 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[cellIdInMesh2D]]));
9153 unsigned sz(cm.getNumberOfSons2(c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1));
9154 if(sz!=std::distance(descBg,descEnd))
9155 throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 1 !");
9156 INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]]);
9157 std::vector<int> allEdges,centers;
9158 const double *coordsPtr(coords->begin());
9159 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
9160 int offset(coords->getNumberOfTuples());
9161 for(const int *it2(descBg);it2!=descEnd;it2++,ii++)
9163 INTERP_KERNEL::NormalizedCellType typeOfSon;
9164 cm.fillSonCellNodalConnectivity2(ii,c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1,tmpPtr,typeOfSon);
9165 const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9167 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9169 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9171 centers.push_back(tmpPtr[2]);//special case where no subsplit of edge -> reuse the original center.
9173 {//the current edge has been subsplit -> create corresponding centers.
9174 std::size_t nbOfCentersToAppend(edge1.size()/2);
9175 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9176 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpPtr,coordsPtr,m));
9177 std::vector<int>::const_iterator it3(allEdges.end()-edge1.size());
9178 for(std::size_t k=0;k<nbOfCentersToAppend;k++)
9181 const double *aa(coordsPtr+2*(*it3++));
9182 const double *bb(coordsPtr+2*(*it3++));
9183 ee->getMiddleOfPoints(aa,bb,tmpp);
9184 addCoo->insertAtTheEnd(tmpp,tmpp+2);
9185 centers.push_back(offset+k);
9189 std::size_t nb(allEdges.size());
9191 throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 2 !");
9192 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9193 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9195 ret->setCoords(coords);
9198 addCoo->rearrange(2);
9199 addCoo=DataArrayDouble::Aggregate(coords,addCoo);
9200 ret->setCoords(addCoo);
9202 ret->allocateCells(1);
9203 std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9204 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9205 connOut[kk]=allEdges[2*kk];
9206 connOut.insert(connOut.end(),centers.begin(),centers.end());
9207 ret->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,connOut.size(),&connOut[0]);
9212 * This method creates a refinement of a cell in \a mesh2D. Those cell is defined by descending connectivity and the sorted subdivided nodal connectivity
9215 * \param [in] mesh2D - The origin 2D mesh. \b Warning \b coords are not those of \a mesh2D. But mesh2D->getCoords()==coords[:mesh2D->getNumberOfNodes()]
9217 MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9219 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(mesh2D->getTypeOfCell(cellIdInMesh2D)));
9220 if(!cm.isQuadratic())
9221 return BuildRefined2DCellLinear(coords,descBg,descEnd,intersectEdge1);
9223 return BuildRefined2DCellQuadratic(coords,mesh2D,cellIdInMesh2D,descBg,descEnd,intersectEdge1);
9226 void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector<int>& conn, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edges)
9229 for(std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >::const_iterator it=edges.begin();it!=edges.end();it++)
9231 const INTERP_KERNEL::Edge *ee(*it);
9232 if(dynamic_cast<const INTERP_KERNEL::EdgeArcCircle *>(ee))
9236 mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]);
9239 const double *coo(mesh2D->getCoords()->begin());
9240 std::size_t sz(conn.size());
9241 std::vector<double> addCoo;
9242 std::vector<int> conn2(conn);
9243 int offset(mesh2D->getNumberOfNodes());
9244 for(std::size_t i=0;i<sz;i++)
9247 edges[(i+1)%sz]->getMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);// tony a chier i+1 -> i
9248 addCoo.insert(addCoo.end(),tmp,tmp+2);
9249 conn2.push_back(offset+(int)i);
9251 mesh2D->getCoords()->rearrange(1);
9252 mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size());
9253 mesh2D->getCoords()->rearrange(2);
9254 mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]);
9259 * \b WARNING edges in out1 coming from \a splitMesh1D are \b NOT oriented because only used for equation of curve.
9261 * This method cuts in 2 parts the input 2D cell given using boundaries description (\a edge1Bis and \a edge1BisPtr) using
9262 * a set of edges defined in \a splitMesh1D.
9264 void BuildMesh2DCutInternal2(const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& edge1Bis, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edge1BisPtr,
9265 std::vector< std::vector<int> >& out0, std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& out1)
9267 std::size_t nb(edge1Bis.size()/2);
9268 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9269 int iEnd(splitMesh1D->getNumberOfCells());
9271 throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal2 : internal error ! input 1D mesh must have at least one cell !");
9273 const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9274 for(ii=0;ii<nb && edge1Bis[2*ii]!=cSplitPtr[ciSplitPtr[0]+1];ii++);
9275 for(jj=ii;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd-1]+2];jj++);
9278 {//the edges splitMesh1D[iStart:iEnd] does not fully cut the current 2D cell -> single output cell
9279 out0.resize(1); out1.resize(1);
9280 std::vector<int>& connOut(out0[0]);
9281 connOut.resize(nbOfEdgesOf2DCellSplit);
9282 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr(out1[0]);
9283 edgesPtr.resize(nbOfEdgesOf2DCellSplit);
9284 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9286 connOut[kk]=edge1Bis[2*kk];
9287 edgesPtr[kk]=edge1BisPtr[2*kk];
9292 // [i,iEnd[ contains the
9293 out0.resize(2); out1.resize(2);
9294 std::vector<int>& connOutLeft(out0[0]);
9295 std::vector<int>& connOutRight(out0[1]);//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1]
9296 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eleft(out1[0]);
9297 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eright(out1[1]);
9298 for(std::size_t k=ii;k<jj+1;k++)
9299 { connOutLeft.push_back(edge1Bis[2*k+1]); eleft.push_back(edge1BisPtr[2*k+1]); }
9300 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > ees(iEnd);
9301 for(int ik=0;ik<iEnd;ik++)
9303 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9304 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9307 for(int ik=iEnd-1;ik>=0;ik--)
9308 connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]);
9309 for(std::size_t k=jj+1;k<nbOfEdgesOf2DCellSplit+ii;k++)
9310 { connOutRight.push_back(edge1Bis[2*k+1]); eright.push_back(edge1BisPtr[2*k+1]); }
9311 eleft.insert(eleft.end(),ees.rbegin(),ees.rend());
9312 for(int ik=0;ik<iEnd;ik++)
9313 connOutRight.push_back(cSplitPtr[ciSplitPtr[ik]+2]);
9314 eright.insert(eright.end(),ees.begin(),ees.end());
9326 CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9328 std::vector<int> _edges;
9329 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > _edges_ptr;
9332 CellInfo::CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr)
9334 std::size_t nbe(edges.size());
9335 std::vector<int> edges2(2*nbe); std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edgesPtr2(2*nbe);
9336 for(std::size_t i=0;i<nbe;i++)
9338 edges2[2*i]=edges[i]; edges2[2*i+1]=edges[(i+1)%nbe];
9339 edgesPtr2[2*i]=edgesPtr[(i+1)%nbe]; edgesPtr2[2*i+1]=edgesPtr[(i+1)%nbe];//tony a chier
9341 _edges.resize(4*nbe); _edges_ptr.resize(4*nbe);
9342 std::copy(edges2.begin(),edges2.end(),_edges.begin()); std::copy(edges2.begin(),edges2.end(),_edges.begin()+2*nbe);
9343 std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()); std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()+2*nbe);
9349 EdgeInfo(int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh):_istart(istart),_iend(iend),_mesh(mesh),_left(-7),_right(-7) { }
9350 EdgeInfo(int istart, int iend, int pos, const MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge>& edge):_istart(istart),_iend(iend),_edge(edge),_left(pos),_right(pos+1) { }
9351 bool isInMyRange(int pos) const { return pos>=_istart && pos<_iend; }
9352 void somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9353 void feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const;
9357 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _mesh;
9358 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> _edge;
9363 void EdgeInfo::somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9365 const MEDCouplingUMesh *mesh(_mesh);
9371 { _left++; _right++; return ; }
9374 bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9375 if((isLeft && isRight) || (!isLeft && !isRight))
9376 throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 1 !");
9387 bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9388 if((isLeft && isRight) || (!isLeft && !isRight))
9389 throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 2 !");
9404 void EdgeInfo::feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const
9406 const MEDCouplingUMesh *mesh(_mesh);
9409 neighbors[0]=offset+_left; neighbors[1]=offset+_right;
9412 {// not fully splitting cell case
9413 if(mesh2D->getNumberOfCells()==1)
9414 {//little optimization. 1 cell no need to find in which cell mesh is !
9415 neighbors[0]=offset; neighbors[1]=offset;
9420 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9421 int cellId(mesh2D->getCellContainingPoint(barys->begin(),eps));
9423 throw INTERP_KERNEL::Exception("EdgeInfo::feedEdgeInfoAt : internal error !");
9424 neighbors[0]=offset+cellId; neighbors[1]=offset+cellId;
9429 class VectorOfCellInfo
9432 VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9433 std::size_t size() const { return _pool.size(); }
9434 int getPositionOf(double eps, const MEDCouplingUMesh *mesh) const;
9435 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);
9436 const std::vector<int>& getConnOf(int pos) const { return get(pos)._edges; }
9437 const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& getEdgePtrOf(int pos) const { return get(pos)._edges_ptr; }
9438 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> getZeMesh() const { return _ze_mesh; }
9439 void feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const;
9441 int getZePosOfEdgeGivenItsGlobalId(int pos) const;
9442 void updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9443 const CellInfo& get(int pos) const;
9444 CellInfo& get(int pos);
9446 std::vector<CellInfo> _pool;
9447 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _ze_mesh;
9448 std::vector<EdgeInfo> _edge_info;
9451 VectorOfCellInfo::VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr):_pool(1)
9453 _pool[0]._edges=edges;
9454 _pool[0]._edges_ptr=edgesPtr;
9457 int VectorOfCellInfo::getPositionOf(double eps, const MEDCouplingUMesh *mesh) const
9460 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : empty !");
9463 const MEDCouplingUMesh *zeMesh(_ze_mesh);
9465 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : null aggregated mesh !");
9466 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9467 return zeMesh->getCellContainingPoint(barys->begin(),eps);
9470 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)
9472 get(pos);//to check pos
9473 bool isFast(pos==0 && _pool.size()==1);
9474 std::size_t sz(edges.size());
9475 // dealing with edges
9477 _edge_info.push_back(EdgeInfo(istart,iend,mesh1DInCase));
9479 _edge_info.push_back(EdgeInfo(istart,iend,pos,edgePtrs[0].back()));
9481 std::vector<CellInfo> pool(_pool.size()-1+sz);
9482 for(int i=0;i<pos;i++)
9484 for(std::size_t j=0;j<sz;j++)
9485 pool[pos+j]=CellInfo(edges[j],edgePtrs[j]);
9486 for(int i=pos+1;i<(int)_pool.size();i++)
9487 pool[i+sz-1]=_pool[i];
9491 updateEdgeInfo(pos,edgePtrs[0],edgePtrs[1]);
9499 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > ms;
9502 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(0,pos,true)));
9506 if(pos<_ze_mesh->getNumberOfCells()-1)
9508 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(pos+1,_ze_mesh->getNumberOfCells(),true)));
9511 std::vector< const MEDCouplingUMesh *> ms2(ms.size());
9512 for(std::size_t j=0;j<ms2.size();j++)
9514 _ze_mesh=MEDCouplingUMesh::MergeUMeshesOnSameCoords(ms2);
9517 void VectorOfCellInfo::feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const
9519 _edge_info[getZePosOfEdgeGivenItsGlobalId(pos)].feedEdgeInfoAt(eps,_ze_mesh,offset,neighbors);
9522 int VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId(int pos) const
9525 throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id ! Must be >=0 !");
9527 for(std::vector<EdgeInfo>::const_iterator it=_edge_info.begin();it!=_edge_info.end();it++,ret++)
9529 if((*it).isInMyRange(pos))
9532 throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id !");
9535 void VectorOfCellInfo::updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9537 get(pos);//to check;
9538 if(_edge_info.empty())
9540 std::size_t sz(_edge_info.size()-1);
9541 for(std::size_t i=0;i<sz;i++)
9542 _edge_info[i].somethingHappendAt(pos,newLeft,newRight);
9545 const CellInfo& VectorOfCellInfo::get(int pos) const
9547 if(pos<0 || pos>=(int)_pool.size())
9548 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get const : invalid pos !");
9552 CellInfo& VectorOfCellInfo::get(int pos)
9554 if(pos<0 || pos>=(int)_pool.size())
9555 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get : invalid pos !");
9561 * - a \b closed set of edges ( \a allEdges and \a allEdgesPtr ) that defines the split descending 2D cell.
9562 * - \a splitMesh1D a split 2D curve mesh contained into 2D cell defined above.
9564 * This method returns the 2D mesh and feeds \a idsLeftRight using offset.
9566 * Algorithm : \a splitMesh1D is cut into contiguous parts. Each contiguous parts will build incrementally the output 2D cells.
9568 * \param [in] allEdges a list of pairs (beginNode, endNode). Linked with \a allEdgesPtr to get the equation of edge.
9570 MEDCouplingUMesh *BuildMesh2DCutInternal(double eps, const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& allEdges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& allEdgesPtr, int offset,
9571 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9573 int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells());
9574 if(nbCellsInSplitMesh1D==0)
9575 throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal : internal error ! input 1D mesh must have at least one cell !");
9576 const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9577 std::size_t nb(allEdges.size()),jj;
9579 throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !");
9580 std::vector<int> edge1Bis(nb*2);
9581 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edge1BisPtr(nb*2);
9582 std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin());
9583 std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb);
9584 std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin());
9585 std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb);
9587 idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(nbCellsInSplitMesh1D*2); idsLeftRight->fillWithValue(-2); idsLeftRight->rearrange(2);
9588 int *idsLeftRightPtr(idsLeftRight->getPointer());
9589 VectorOfCellInfo pool(edge1Bis,edge1BisPtr);
9590 for(int iStart=0;iStart<nbCellsInSplitMesh1D;)
9591 {// split [0:nbCellsInSplitMesh1D) in contiguous parts [iStart:iEnd)
9593 for(;iEnd<nbCellsInSplitMesh1D;)
9595 for(jj=0;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd]+2];jj++);
9601 if(iEnd<nbCellsInSplitMesh1D)
9604 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfSplitMesh1D(static_cast<MEDCouplingUMesh *>(splitMesh1D->buildPartOfMySelf2(iStart,iEnd,1,true)));
9605 int pos(pool.getPositionOf(eps,partOfSplitMesh1D));
9607 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>retTmp(MEDCouplingUMesh::New("",2));
9608 retTmp->setCoords(splitMesh1D->getCoords());
9609 retTmp->allocateCells();
9611 std::vector< std::vector<int> > out0;
9612 std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > > out1;
9614 BuildMesh2DCutInternal2(partOfSplitMesh1D,pool.getConnOf(pos),pool.getEdgePtrOf(pos),out0,out1);
9615 for(std::size_t cnt=0;cnt<out0.size();cnt++)
9616 AddCellInMesh2D(retTmp,out0[cnt],out1[cnt]);
9617 pool.setMeshAt(pos,retTmp,iStart,iEnd,partOfSplitMesh1D,out0,out1);
9621 for(int mm=0;mm<nbCellsInSplitMesh1D;mm++)
9622 pool.feedEdgeInfoAt(eps,mm,offset,idsLeftRightPtr+2*mm);
9623 return pool.getZeMesh().retn();
9626 MEDCouplingUMesh *BuildMesh2DCutFrom(double eps, int cellIdInMesh2D, const MEDCouplingUMesh *mesh2DDesc, const MEDCouplingUMesh *splitMesh1D,
9627 const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1, int offset,
9628 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9630 const int *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin());
9632 std::vector<int> allEdges;
9633 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > allEdgesPtr; // for each sub edge in splitMesh2D the uncut Edge object of the original mesh2D
9634 for(const int *it(descBg);it!=descEnd;it++) // for all edges in the descending connectivity of the 2D mesh in relative Fortran mode
9636 int edgeId(std::abs(*it)-1);
9637 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9638 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m));
9639 const std::vector<int>& edge1(intersectEdge1[edgeId]);
9641 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9643 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9644 std::size_t sz(edge1.size());
9645 for(std::size_t cnt=0;cnt<sz;cnt++)
9646 allEdgesPtr.push_back(ee);
9649 return BuildMesh2DCutInternal(eps,splitMesh1D,allEdges,allEdgesPtr,offset,idsLeftRight);
9652 bool AreEdgeEqual(const double *coo2D, const INTERP_KERNEL::CellModel& typ1, const int *conn1, const INTERP_KERNEL::CellModel& typ2, const int *conn2, double eps)
9654 if(!typ1.isQuadratic() && !typ2.isQuadratic())
9655 {//easy case comparison not
9656 return conn1[0]==conn2[0] && conn1[1]==conn2[1];
9658 else if(typ1.isQuadratic() && typ2.isQuadratic())
9660 bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9663 if(conn1[2]==conn2[2])
9665 const double *a(coo2D+2*conn1[2]),*b(coo2D+2*conn2[2]);
9666 double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9670 {//only one is quadratic
9671 bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9674 const double *a(0),*bb(0),*be(0);
9675 if(typ1.isQuadratic())
9677 a=coo2D+2*conn1[2]; bb=coo2D+2*conn2[0]; be=coo2D+2*conn2[1];
9681 a=coo2D+2*conn2[2]; bb=coo2D+2*conn1[0]; be=coo2D+2*conn1[1];
9683 double b[2]; b[0]=(be[0]+bb[0])/2.; b[1]=(be[1]+bb[1])/2.;
9684 double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9690 * This method returns among the cellIds [ \a candidatesIn2DBg , \a candidatesIn2DEnd ) in \a mesh2DSplit those exactly sharing \a cellIdInMesh1DSplitRelative in \a mesh1DSplit.
9691 * \a mesh2DSplit and \a mesh1DSplit are expected to share the coordinates array.
9693 * \param [in] cellIdInMesh1DSplitRelative is in Fortran mode using sign to specify direction.
9695 int FindRightCandidateAmong(const MEDCouplingUMesh *mesh2DSplit, const int *candidatesIn2DBg, const int *candidatesIn2DEnd, const MEDCouplingUMesh *mesh1DSplit, int cellIdInMesh1DSplitRelative, double eps)
9697 if(candidatesIn2DEnd==candidatesIn2DBg)
9698 throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 1 !");
9699 const double *coo(mesh2DSplit->getCoords()->begin());
9700 if(std::distance(candidatesIn2DBg,candidatesIn2DEnd)==1)
9701 return *candidatesIn2DBg;
9702 int edgeId(std::abs(cellIdInMesh1DSplitRelative)-1);
9703 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur1D(static_cast<MEDCouplingUMesh *>(mesh1DSplit->buildPartOfMySelf(&edgeId,&edgeId+1,true)));
9704 if(cellIdInMesh1DSplitRelative<0)
9705 cur1D->changeOrientationOfCells();
9706 const int *c1D(cur1D->getNodalConnectivity()->begin());
9707 const INTERP_KERNEL::CellModel& ref1DType(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c1D[0]));
9708 for(const int *it=candidatesIn2DBg;it!=candidatesIn2DEnd;it++)
9710 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur2D(static_cast<MEDCouplingUMesh *>(mesh2DSplit->buildPartOfMySelf(it,it+1,true)));
9711 const int *c(cur2D->getNodalConnectivity()->begin()),*ci(cur2D->getNodalConnectivityIndex()->begin());
9712 const INTERP_KERNEL::CellModel &cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[0]]));
9713 unsigned sz(cm.getNumberOfSons2(c+ci[0]+1,ci[1]-ci[0]-1));
9714 INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[1]-ci[0]]);
9715 for(unsigned it2=0;it2<sz;it2++)
9717 INTERP_KERNEL::NormalizedCellType typeOfSon;
9718 cm.fillSonCellNodalConnectivity2(it2,c+ci[0]+1,ci[1]-ci[0]-1,tmpPtr,typeOfSon);
9719 const INTERP_KERNEL::CellModel &curCM(INTERP_KERNEL::CellModel::GetCellModel(typeOfSon));
9720 if(AreEdgeEqual(coo,ref1DType,c1D+1,curCM,tmpPtr,eps))
9724 throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 2 ! Unable to find the edge among split cell !");
9730 * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
9731 * 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
9732 * and finaly, in case of quadratic polygon the centers of edges new nodes.
9733 * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
9735 * \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
9736 * 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)
9737 * \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
9738 * you can invoke orderConsecutiveCells1D on \a mesh1D.
9739 * \param [in] eps - precision used to perform intersections and localization operations.
9740 * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
9741 * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
9742 * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
9743 * 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.
9744 * \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
9745 * and the cell in \a splitMesh2D on the right for the 2nt component. -1 means no cell.
9746 * 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.
9748 * \sa Intersect2DMeshes, orderConsecutiveCells1D, conformize2D, mergeNodes
9750 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
9752 if(!mesh2D || !mesh1D)
9753 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
9754 mesh2D->checkFullyDefined();
9755 mesh1D->checkFullyDefined();
9756 const std::vector<std::string>& compNames(mesh2D->getCoords()->getInfoOnComponents());
9757 if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
9758 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
9759 // Step 1: compute all edge intersections (new nodes)
9760 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9761 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
9762 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9763 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9765 // Build desc connectivity
9766 DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
9767 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9768 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
9769 std::map<int,int> mergedNodes;
9770 Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes);
9771 // use mergeNodes to fix intersectEdge1
9772 for(std::vector< std::vector<int> >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++)
9774 std::size_t n((*it0).size()/2);
9775 int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]);
9776 std::map<int,int>::const_iterator it1;
9777 it1=mergedNodes.find(eltStart);
9778 if(it1!=mergedNodes.end())
9779 (*it0)[0]=(*it1).second;
9780 it1=mergedNodes.find(eltEnd);
9781 if(it1!=mergedNodes.end())
9782 (*it0)[2*n-1]=(*it1).second;
9785 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9786 addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9787 // Step 2: re-order newly created nodes according to the ordering found in m2
9788 std::vector< std::vector<int> > intersectEdge2;
9789 BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
9791 // Step 3: compute splitMesh1D
9792 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear;
9793 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2(DataArrayInt::New()); ret2->alloc(0,1);
9794 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1,
9795 idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear));
9796 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(std::numeric_limits<int>::max()); ret3->rearrange(2);
9797 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells()));
9798 // deal with cells in mesh2D that are not cut but only some of their edges are
9799 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCpy());
9800 idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1);
9801 idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique();
9802 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
9803 if(!idsInDesc2DToBeRefined->empty())
9805 DataArrayInt *out0(0),*outi0(0);
9806 MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
9807 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> outi0s(outi0);
9809 out0s=out0s->buildUnique();
9813 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1NonCol(static_cast<MEDCouplingUMesh *>(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end())));
9814 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> baryRet1(ret1NonCol->getBarycenterAndOwner());
9815 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elts,eltsIndex;
9816 mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
9817 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex2(eltsIndex->deltaShiftIndex());
9818 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex3(eltsIndex2->getIdsEqual(1));
9819 if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells())
9820 throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !");
9821 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToBeModified(elts->buildUnique());
9822 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells()));
9823 if((DataArrayInt *)out0s)
9824 untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one
9825 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > outMesh2DSplit;
9826 // OK all is ready to insert in ret2 mesh
9827 if(!untouchedCells->empty())
9828 {// the most easy part, cells in mesh2D not impacted at all
9829 outMesh2DSplit.push_back(static_cast<MEDCouplingUMesh *>(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end())));
9830 outMesh2DSplit.back()->setCoords(ret1->getCoords());
9831 ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end());
9833 if((DataArrayInt *)out0s)
9834 {// here dealing with cells in out0s but not in cellsToBeModified
9835 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fewModifiedCells(out0s->buildSubstraction(cellsToBeModified));
9836 const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin());
9837 for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++)
9839 outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),mesh2D,*it,dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1));
9840 ret1->setCoords(outMesh2DSplit.back()->getCoords());
9842 int offset(ret2->getNumberOfTuples());
9843 ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end());
9844 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1);
9845 partOfRet3->fillWithValue(std::numeric_limits<int>::max()); partOfRet3->rearrange(2);
9846 int kk(0),*ret3ptr(partOfRet3->getPointer());
9847 for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++)
9849 int faceId(std::abs(*it)-1);
9850 for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++)
9852 int tmp(fewModifiedCells->locateValue(*it2));
9855 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9856 ret3ptr[2*kk]=tmp+offset;
9857 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9858 ret3ptr[2*kk+1]=tmp+offset;
9861 {//the current edge is shared by a 2D cell that will be split just after
9862 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9863 ret3ptr[2*kk]=-(*it2+1);
9864 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9865 ret3ptr[2*kk+1]=-(*it2+1);
9869 m1Desc->setCoords(ret1->getCoords());
9870 ret1NonCol->setCoords(ret1->getCoords());
9871 ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true);
9872 if(!outMesh2DSplit.empty())
9874 DataArrayDouble *da(outMesh2DSplit.back()->getCoords());
9875 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> >::iterator itt=outMesh2DSplit.begin();itt!=outMesh2DSplit.end();itt++)
9876 (*itt)->setCoords(da);
9879 cellsToBeModified=cellsToBeModified->buildUniqueNotSorted();
9880 for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++)
9882 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell(elts->getIdsEqual(*it));
9883 idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end());
9884 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end()));
9885 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfMesh1CuttingCur2DCell(static_cast<MEDCouplingUMesh *>(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end())));
9886 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3;
9887 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));
9888 ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true);
9889 outMesh2DSplit.push_back(splitOfOneCell);
9890 for(int i=0;i<splitOfOneCell->getNumberOfCells();i++)
9891 ret2->pushBackSilent(*it);
9894 std::size_t nbOfMeshes(outMesh2DSplit.size());
9895 std::vector<const MEDCouplingUMesh *> tmp(nbOfMeshes);
9896 for(std::size_t i=0;i<nbOfMeshes;i++)
9897 tmp[i]=outMesh2DSplit[i];
9899 ret1->getCoords()->setInfoOnComponents(compNames);
9900 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2D(MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp));
9901 // To finish - filter ret3 - std::numeric_limits<int>::max() -> -1 - negate values must be resolved.
9903 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> edgesToDealWith(ret3->getIdsStrictlyNegative());
9904 for(const int *it=edgesToDealWith->begin();it!=edgesToDealWith->end();it++)
9906 int old2DCellId(-ret3->getIJ(*it,0)-1);
9907 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates(ret2->getIdsEqual(old2DCellId));
9908 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
9910 ret3->replaceOneValByInThis(std::numeric_limits<int>::max(),-1);
9913 splitMesh1D=ret1.retn();
9914 splitMesh2D=ret2D.retn();
9915 cellIdInMesh2D=ret2.retn();
9916 cellIdInMesh1D=ret3.retn();
9920 * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
9921 * (newly created) nodes corresponding to the edge intersections.
9923 * @param[out] cr, crI connectivity of the resulting mesh
9924 * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
9925 * TODO: describe input parameters
9927 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
9928 const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
9929 const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
9930 const std::vector<double>& addCoords,
9931 std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
9933 static const int SPACEDIM=2;
9934 const double *coo1(m1->getCoords()->getConstPointer());
9935 const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer());
9936 int offset1(m1->getNumberOfNodes());
9937 const double *coo2(m2->getCoords()->getConstPointer());
9938 const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer());
9939 int offset2(offset1+m2->getNumberOfNodes());
9940 int offset3(offset2+((int)addCoords.size())/2);
9941 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
9942 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9943 // Here a BBTree on 2D-cells, not on segments:
9944 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
9945 int ncell1(m1->getNumberOfCells());
9947 for(int i=0;i<ncell1;i++)
9949 std::vector<int> candidates2;
9950 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9951 std::map<INTERP_KERNEL::Node *,int> mapp;
9952 std::map<int,INTERP_KERNEL::Node *> mappRev;
9953 INTERP_KERNEL::QuadraticPolygon pol1;
9954 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
9955 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
9956 // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
9957 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
9958 // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
9959 pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
9960 desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
9962 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
9963 std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
9964 INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
9965 for(it1.first();!it1.finished();it1.next())
9966 edges1.insert(it1.current()->getPtr());
9968 std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
9969 std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
9971 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9973 INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
9974 const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
9975 // Complete mapping with elements coming from the current cell it2 in mesh2:
9976 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
9977 // pol2 is the new QP in the final merged result.
9978 pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
9979 pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
9982 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9984 INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
9985 pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
9986 //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
9987 pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9989 // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
9990 // by m2 but that we still want to keep in the final result.
9995 INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9997 catch(INTERP_KERNEL::Exception& e)
9999 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();
10000 throw INTERP_KERNEL::Exception(oss.str().c_str());
10003 for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
10004 (*it).second->decrRef();
10009 * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
10010 * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
10011 * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
10012 * The caller is to deal with the resulting DataArrayInt.
10013 * \throw If the coordinate array is not set.
10014 * \throw If the nodal connectivity of the cells is not defined.
10015 * \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
10016 * \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
10018 * \sa DataArrayInt::sortEachPairToMakeALinkedList
10020 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
10022 checkFullyDefined();
10023 if(getMeshDimension()!=1)
10024 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
10026 // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
10027 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
10028 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
10029 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
10030 const int *d(_d->getConstPointer()), *dI(_dI->getConstPointer());
10031 const int *rD(_rD->getConstPointer()), *rDI(_rDI->getConstPointer());
10032 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
10033 const int * dsi(_dsi->getConstPointer());
10034 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dsii = _dsi->getIdsNotInRange(0,3);
10036 if (dsii->getNumberOfTuples())
10037 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
10039 int nc(getNumberOfCells());
10040 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> result(DataArrayInt::New());
10041 result->alloc(nc,1);
10043 // set of edges not used so far
10044 std::set<int> edgeSet;
10045 for (int i=0; i<nc; edgeSet.insert(i), i++);
10049 // while we have points with only one neighbor segments
10052 std::list<int> linePiece;
10053 // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
10054 for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
10056 // Fill the list forward (resp. backward) from the start segment:
10057 int activeSeg = startSeg;
10058 int prevPointId = -20;
10060 while (!edgeSet.empty())
10062 if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
10065 linePiece.push_back(activeSeg);
10067 linePiece.push_front(activeSeg);
10068 edgeSet.erase(activeSeg);
10071 int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
10072 ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
10073 if (dsi[ptId] == 1) // hitting the end of the line
10075 prevPointId = ptId;
10076 int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
10077 activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
10080 // Done, save final piece into DA:
10081 std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
10082 newIdx += linePiece.size();
10084 // identify next valid start segment (one which is not consumed)
10085 if(!edgeSet.empty())
10086 startSeg = *(edgeSet.begin());
10088 while (!edgeSet.empty());
10089 return result.retn();
10094 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10096 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> nTmp(n); nTmp->incrRef();
10097 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>::const_iterator it(m.find(nTmp));
10099 throw INTERP_KERNEL::Exception("Internal error in remapping !");
10100 int v((*it).second);
10101 if(v==forbVal0 || v==forbVal1)
10103 if(std::find(isect.begin(),isect.end(),v)==isect.end())
10104 isect.push_back(v);
10107 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10112 bool presenceOfOn(false);
10113 for(int i=0;i<sz;i++)
10115 INTERP_KERNEL::ElementaryEdge *e(c[i]);
10116 if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
10118 IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
10119 IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
10121 return presenceOfOn;
10127 * 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.
10128 * 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.
10129 * 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.
10130 * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to avoid to have a non conform mesh.
10132 * \return int - the number of new nodes created (in most of cases 0).
10134 * \throw If \a this is not coherent.
10135 * \throw If \a this has not spaceDim equal to 2.
10136 * \throw If \a this has not meshDim equal to 2.
10137 * \throw If some subcells needed to be split are orphan.
10138 * \sa MEDCouplingUMesh::conformize2D
10140 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
10142 if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
10143 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
10144 desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
10145 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10146 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10147 if(midOpt==0 && midOptI==0)
10149 split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
10152 else if(midOpt!=0 && midOptI!=0)
10153 return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
10155 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
10159 * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
10160 * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
10161 * 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
10162 * 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).
10163 * 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.
10165 * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
10166 * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
10168 * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
10169 * This method expects that all nodes in \a this are not closer than \a eps.
10170 * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
10172 * \param [in] eps the relative error to detect merged edges.
10173 * \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
10174 * that the user is expected to deal with.
10176 * \throw If \a this is not coherent.
10177 * \throw If \a this has not spaceDim equal to 2.
10178 * \throw If \a this has not meshDim equal to 2.
10179 * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
10181 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
10183 static const int SPACEDIM=2;
10185 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10186 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10187 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
10188 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
10189 const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
10190 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
10191 const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
10192 int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
10193 std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
10194 std::vector<double> addCoo;
10195 BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
10196 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10197 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10198 for(int i=0;i<nDescCell;i++)
10200 std::vector<int> candidates;
10201 myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
10202 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
10205 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10206 INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
10207 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
10208 INTERP_KERNEL::MergePoints merge;
10209 INTERP_KERNEL::QuadraticPolygon c1,c2;
10210 e1->intersectWith(e2,merge,c1,c2);
10211 e1->decrRef(); e2->decrRef();
10212 if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
10213 overlapEdge[i].push_back(*it);
10214 if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
10215 overlapEdge[*it].push_back(i);
10218 // splitting done. sort intersect point in intersectEdge.
10219 std::vector< std::vector<int> > middle(nDescCell);
10220 int nbOf2DCellsToBeSplit(0);
10221 bool middleNeedsToBeUsed(false);
10222 std::vector<bool> cells2DToTreat(nDescCell,false);
10223 for(int i=0;i<nDescCell;i++)
10225 std::vector<int>& isect(intersectEdge[i]);
10226 int sz((int)isect.size());
10229 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10230 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
10231 e->sortSubNodesAbs(coords,isect);
10236 int idx0(rdi[i]),idx1(rdi[i+1]);
10238 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
10239 if(!cells2DToTreat[rd[idx0]])
10241 cells2DToTreat[rd[idx0]]=true;
10242 nbOf2DCellsToBeSplit++;
10244 // try to reuse at most eventual 'middle' of SEG3
10245 std::vector<int>& mid(middle[i]);
10246 mid.resize(sz+1,-1);
10247 if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
10249 middleNeedsToBeUsed=true;
10250 const std::vector<int>& candidates(overlapEdge[i]);
10251 std::vector<int> trueCandidates;
10252 for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
10253 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
10254 trueCandidates.push_back(*itc);
10255 int stNode(c[ci[i]+1]),endNode(isect[0]);
10256 for(int j=0;j<sz+1;j++)
10258 for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
10260 int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
10261 if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
10262 { mid[j]=*itc; break; }
10265 endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
10270 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
10271 if(nbOf2DCellsToBeSplit==0)
10274 int *retPtr(ret->getPointer());
10275 for(int i=0;i<nCell;i++)
10276 if(cells2DToTreat[i])
10279 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
10280 DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
10281 MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
10282 DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
10283 if(middleNeedsToBeUsed)
10284 { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
10285 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
10286 int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
10287 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.
10288 setPartOfMySelf(ret->begin(),ret->end(),*modif);
10290 bool areNodesMerged; int newNbOfNodes;
10291 if(nbOfNodesCreated!=0)
10292 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
10298 * 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.
10299 * 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).
10300 * 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
10301 * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
10302 * 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
10303 * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
10305 * 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
10306 * using new instance, idem for coordinates.
10308 * 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.
10310 * \return DataArrayInt * - The list of cellIds in \a this that have at least one edge colinearized.
10312 * \throw If \a this is not coherent.
10313 * \throw If \a this has not spaceDim equal to 2.
10314 * \throw If \a this has not meshDim equal to 2.
10316 * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
10318 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
10320 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
10322 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10323 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10324 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10325 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10326 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
10327 const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
10328 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
10329 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
10330 const double *coords(_coords->begin());
10331 int *newciptr(newci->getPointer());
10332 for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
10334 if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
10335 ret->pushBackSilent(i);
10336 newciptr[1]=newc->getNumberOfTuples();
10341 if(!appendedCoords->empty())
10343 appendedCoords->rearrange(2);
10344 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
10346 setCoords(newCoords);
10349 setConnectivity(newc,newci,true);
10354 * \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.
10355 * 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.
10356 * And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
10357 * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
10358 * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
10359 * \param [out] addCoo - nodes to be append at the end
10360 * \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.
10362 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
10363 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)
10365 static const int SPACEDIM=2;
10366 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10367 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10368 const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer());
10369 // Build BB tree of all edges in the tool mesh (second mesh)
10370 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
10371 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10372 int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
10373 intersectEdge1.resize(nDescCell1);
10374 colinear2.resize(nDescCell2);
10375 subDiv2.resize(nDescCell2);
10376 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
10378 std::vector<int> candidates1(1);
10379 int offset1(m1Desc->getNumberOfNodes());
10380 int offset2(offset1+m2Desc->getNumberOfNodes());
10381 for(int i=0;i<nDescCell1;i++) // for all edges in the first mesh
10383 std::vector<int> candidates2; // edges of mesh2 candidate for intersection
10384 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10385 if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
10387 std::map<INTERP_KERNEL::Node *,int> map1,map2;
10388 // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
10389 INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
10391 INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
10392 // 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
10393 // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
10394 std::set<INTERP_KERNEL::Node *> nodes;
10395 pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
10396 std::size_t szz(nodes.size());
10397 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
10398 std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
10399 for(std::size_t iii=0;iii<szz;iii++,itt++)
10400 { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
10401 // end of protection
10402 // Performs egde cutting:
10403 pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes);
10408 // Copy the edge (take only the two first points, ie discard quadratic point at this stage)
10409 intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i]+3);
10414 * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
10415 * It builds the descending connectivity of the two meshes, and then using a binary tree
10416 * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
10417 * Documentation about parameters colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
10419 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
10420 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
10421 MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
10422 std::vector<double>& addCoo,
10423 MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
10425 // Build desc connectivity
10426 desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
10427 desc2=DataArrayInt::New();
10428 descIndx2=DataArrayInt::New();
10429 revDesc2=DataArrayInt::New();
10430 revDescIndx2=DataArrayInt::New();
10431 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
10432 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
10433 m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
10434 m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
10435 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
10436 std::map<int,int> notUsedMap;
10437 Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap);
10438 m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
10439 m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
10443 * This method performs the 2nd step of Partition of 2D mesh.
10444 * This method has 4 inputs :
10445 * - a mesh 'm1' with meshDim==1 and a SpaceDim==2
10446 * - a mesh 'm2' with meshDim==1 and a SpaceDim==2
10447 * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
10448 * 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'
10449 * Nodes end up lying consecutively on a cutted edge.
10450 * \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.
10451 * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
10452 * \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.
10453 * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
10454 * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
10456 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
10457 const std::vector<double>& addCoo,
10458 const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
10460 int offset1=m1->getNumberOfNodes();
10461 int ncell=m2->getNumberOfCells();
10462 const int *c=m2->getNodalConnectivity()->getConstPointer();
10463 const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
10464 const double *coo=m2->getCoords()->getConstPointer();
10465 const double *cooBis=m1->getCoords()->getConstPointer();
10466 int offset2=offset1+m2->getNumberOfNodes();
10467 intersectEdge.resize(ncell);
10468 for(int i=0;i<ncell;i++,cI++)
10470 const std::vector<int>& divs=subDiv[i];
10471 int nnode=cI[1]-cI[0]-1;
10472 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
10473 std::map<INTERP_KERNEL::Node *, int> mapp22;
10474 for(int j=0;j<nnode;j++)
10476 INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
10477 int nnid=c[(*cI)+j+1];
10478 mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
10479 mapp22[nn]=nnid+offset1;
10481 INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
10482 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
10483 ((*it).second.first)->decrRef();
10484 std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
10485 std::map<INTERP_KERNEL::Node *,int> mapp3;
10486 for(std::size_t j=0;j<divs.size();j++)
10489 INTERP_KERNEL::Node *tmp=0;
10491 tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
10492 else if(id<offset2)
10493 tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
10495 tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
10499 e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
10500 for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
10507 * 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).
10508 * 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
10509 * with a plane. The result will be put in 'cut3DSuf' out parameter.
10510 * \param [in] cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
10511 * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
10512 * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
10513 * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
10514 * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
10515 * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
10516 * \param [in] desc is the descending connectivity 3DSurf->3DCurve
10517 * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
10518 * \param [out] cut3DSuf input/output param.
10520 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
10521 const int *nodal3DCurve, const int *nodalIndx3DCurve,
10522 const int *desc, const int *descIndx,
10523 std::vector< std::pair<int,int> >& cut3DSurf)
10525 std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
10526 int nbOf3DSurfCell=(int)cut3DSurf.size();
10527 for(int i=0;i<nbOf3DSurfCell;i++)
10529 std::vector<int> res;
10530 int offset=descIndx[i];
10531 int nbOfSeg=descIndx[i+1]-offset;
10532 for(int j=0;j<nbOfSeg;j++)
10534 int edgeId=desc[offset+j];
10535 int status=cut3DCurve[edgeId];
10539 res.push_back(status);
10542 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
10543 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
10551 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10557 std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
10558 std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
10561 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10565 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
10570 {// case when plane is on a multi colinear edge of a polyhedron
10571 if((int)res.size()==2*nbOfSeg)
10573 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
10576 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
10583 * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
10584 * 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).
10585 * 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
10586 * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
10587 * \param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
10588 * \param desc is the descending connectivity 3D->3DSurf
10589 * \param descIndx is the descending connectivity index 3D->3DSurf
10591 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
10592 const int *desc, const int *descIndx,
10593 DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
10595 checkFullyDefined();
10596 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10597 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
10598 const int *nodal3D=_nodal_connec->getConstPointer();
10599 const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
10600 int nbOfCells=getNumberOfCells();
10601 for(int i=0;i<nbOfCells;i++)
10603 std::map<int, std::set<int> > m;
10604 int offset=descIndx[i];
10605 int nbOfFaces=descIndx[i+1]-offset;
10608 for(int j=0;j<nbOfFaces;j++)
10610 const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
10611 if(p.first!=-1 && p.second!=-1)
10615 start=p.first; end=p.second;
10616 m[p.first].insert(p.second);
10617 m[p.second].insert(p.first);
10621 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
10622 int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
10623 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
10624 INTERP_KERNEL::NormalizedCellType cmsId;
10625 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
10626 start=tmp[0]; end=tmp[nbOfNodesSon-1];
10627 for(unsigned k=0;k<nbOfNodesSon;k++)
10629 m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
10630 m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
10637 std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
10641 std::map<int, std::set<int> >::const_iterator it=m.find(start);
10642 const std::set<int>& s=(*it).second;
10643 std::set<int> s2; s2.insert(prev);
10645 std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
10648 int val=*s3.begin();
10649 conn.push_back(start);
10656 conn.push_back(end);
10659 nodalRes->insertAtTheEnd(conn.begin(),conn.end());
10660 nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
10661 cellIds->pushBackSilent(i);
10667 * 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
10668 * 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
10669 * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
10670 * 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
10671 * 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.
10673 * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
10675 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
10677 std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
10680 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
10681 if(cm.getDimension()==2)
10683 const int *node=nodalConnBg+1;
10684 int startNode=*node++;
10685 double refX=coords[2*startNode];
10686 for(;node!=nodalConnEnd;node++)
10688 if(coords[2*(*node)]<refX)
10691 refX=coords[2*startNode];
10694 std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
10698 double angle0=-M_PI/2;
10703 double angleNext=0.;
10704 while(nextNode!=startNode)
10708 for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
10710 if(*node!=tmpOut.back() && *node!=prevNode)
10712 tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
10713 double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
10718 res=angle0-angleM+2.*M_PI;
10727 if(nextNode!=startNode)
10729 angle0=angleNext-M_PI;
10732 prevNode=tmpOut.back();
10733 tmpOut.push_back(nextNode);
10736 std::vector<int> tmp3(2*(sz-1));
10737 std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
10738 std::copy(nodalConnBg+1,nodalConnEnd,it);
10739 if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
10741 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10744 if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
10746 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10751 nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
10752 nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
10757 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10760 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10764 * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
10765 * 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.
10767 * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
10768 * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
10769 * \param [in,out] arr array in which the remove operation will be done.
10770 * \param [in,out] arrIndx array in the remove operation will modify
10771 * \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])
10772 * \return true if \b arr and \b arrIndx have been modified, false if not.
10774 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
10776 if(!arrIndx || !arr)
10777 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
10778 if(offsetForRemoval<0)
10779 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
10780 std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
10781 int nbOfGrps=arrIndx->getNumberOfTuples()-1;
10782 int *arrIPtr=arrIndx->getPointer();
10784 int previousArrI=0;
10785 const int *arrPtr=arr->getConstPointer();
10786 std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
10787 for(int i=0;i<nbOfGrps;i++,arrIPtr++)
10789 if(*arrIPtr-previousArrI>offsetForRemoval)
10791 for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
10793 if(s.find(*work)==s.end())
10794 arrOut.push_back(*work);
10797 previousArrI=*arrIPtr;
10798 *arrIPtr=(int)arrOut.size();
10800 if(arr->getNumberOfTuples()==(int)arrOut.size())
10802 arr->alloc((int)arrOut.size(),1);
10803 std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
10808 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10809 * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
10810 * The selection of extraction is done standardly in new2old format.
10811 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10813 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10814 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10815 * \param [in] arrIn arr origin array from which the extraction will be done.
10816 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10817 * \param [out] arrOut the resulting array
10818 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10819 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
10821 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10822 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10824 if(!arrIn || !arrIndxIn)
10825 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
10826 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10827 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10828 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
10829 std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
10830 const int *arrInPtr=arrIn->getConstPointer();
10831 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10832 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10834 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10835 int maxSizeOfArr=arrIn->getNumberOfTuples();
10836 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10837 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10838 arrIo->alloc((int)(sz+1),1);
10839 const int *idsIt=idsOfSelectBg;
10840 int *work=arrIo->getPointer();
10843 for(std::size_t i=0;i<sz;i++,work++,idsIt++)
10845 if(*idsIt>=0 && *idsIt<nbOfGrps)
10846 lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
10849 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10850 throw INTERP_KERNEL::Exception(oss.str().c_str());
10856 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
10857 oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
10858 throw INTERP_KERNEL::Exception(oss.str().c_str());
10861 arro->alloc(lgth,1);
10862 work=arro->getPointer();
10863 idsIt=idsOfSelectBg;
10864 for(std::size_t i=0;i<sz;i++,idsIt++)
10866 if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
10867 work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
10870 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
10871 oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10872 throw INTERP_KERNEL::Exception(oss.str().c_str());
10875 arrOut=arro.retn();
10876 arrIndexOut=arrIo.retn();
10880 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10881 * 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 ).
10882 * The selection of extraction is done standardly in new2old format.
10883 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10885 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10886 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10887 * \param [in] arrIn arr origin array from which the extraction will be done.
10888 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10889 * \param [out] arrOut the resulting array
10890 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10891 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
10893 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10894 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10896 if(!arrIn || !arrIndxIn)
10897 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
10898 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10899 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10900 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
10901 int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
10902 const int *arrInPtr=arrIn->getConstPointer();
10903 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10904 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10906 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10907 int maxSizeOfArr=arrIn->getNumberOfTuples();
10908 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10909 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10910 arrIo->alloc((int)(sz+1),1);
10911 int idsIt=idsOfSelectStart;
10912 int *work=arrIo->getPointer();
10915 for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
10917 if(idsIt>=0 && idsIt<nbOfGrps)
10918 lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
10921 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10922 throw INTERP_KERNEL::Exception(oss.str().c_str());
10928 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
10929 oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
10930 throw INTERP_KERNEL::Exception(oss.str().c_str());
10933 arro->alloc(lgth,1);
10934 work=arro->getPointer();
10935 idsIt=idsOfSelectStart;
10936 for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
10938 if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
10939 work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
10942 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
10943 oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10944 throw INTERP_KERNEL::Exception(oss.str().c_str());
10947 arrOut=arro.retn();
10948 arrIndexOut=arrIo.retn();
10952 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10953 * 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
10954 * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
10955 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
10957 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10958 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10959 * \param [in] arrIn arr origin array from which the extraction will be done.
10960 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10961 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
10962 * \param [in] srcArrIndex index array of \b srcArr
10963 * \param [out] arrOut the resulting array
10964 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10966 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
10968 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10969 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
10970 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10972 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10973 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
10974 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10975 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10976 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10977 std::vector<bool> v(nbOfTuples,true);
10979 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10980 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10981 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10983 if(*it>=0 && *it<nbOfTuples)
10986 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
10990 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
10991 throw INTERP_KERNEL::Exception(oss.str().c_str());
10994 srcArrIndexPtr=srcArrIndex->getConstPointer();
10995 arrIo->alloc(nbOfTuples+1,1);
10996 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
10997 const int *arrInPtr=arrIn->getConstPointer();
10998 const int *srcArrPtr=srcArr->getConstPointer();
10999 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11000 int *arroPtr=arro->getPointer();
11001 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11005 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11006 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11010 std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
11011 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11012 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11015 arrOut=arro.retn();
11016 arrIndexOut=arrIo.retn();
11020 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11021 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11023 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
11024 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
11025 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11026 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11027 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
11028 * \param [in] srcArrIndex index array of \b srcArr
11030 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
11032 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11033 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11035 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11036 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
11037 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11038 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11039 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11040 int *arrInOutPtr=arrInOut->getPointer();
11041 const int *srcArrPtr=srcArr->getConstPointer();
11042 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
11044 if(*it>=0 && *it<nbOfTuples)
11046 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
11047 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
11050 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] !";
11051 throw INTERP_KERNEL::Exception(oss.str().c_str());
11056 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
11057 throw INTERP_KERNEL::Exception(oss.str().c_str());
11063 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11064 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11065 * This method start from id 0 that will be contained in output DataArrayInt. It searches then all neighbors of id0 looking at arrIn[arrIndxIn[0]:arrIndxIn[0+1]].
11066 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11067 * A negative value in \b arrIn means that it is ignored.
11068 * 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.
11070 * \param [in] arrIn arr origin array from which the extraction will be done.
11071 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11072 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11073 * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
11075 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
11077 int seed=0,nbOfDepthPeelingPerformed=0;
11078 return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
11082 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11083 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11084 * 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]].
11085 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11086 * A negative value in \b arrIn means that it is ignored.
11087 * 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.
11088 * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
11089 * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
11090 * \param [in] arrIn arr origin array from which the extraction will be done.
11091 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11092 * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
11093 * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
11094 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11095 * \sa MEDCouplingUMesh::partitionBySpreadZone
11097 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11099 nbOfDepthPeelingPerformed=0;
11101 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
11102 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11105 DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
11109 std::vector<bool> fetched(nbOfTuples,false);
11110 return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
11113 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11115 nbOfDepthPeelingPerformed=0;
11116 if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
11117 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
11118 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11119 std::vector<bool> fetched2(nbOfTuples,false);
11121 for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
11123 if(*seedElt>=0 && *seedElt<nbOfTuples)
11124 { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
11126 { 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()); }
11128 const int *arrInPtr=arrIn->getConstPointer();
11129 const int *arrIndxPtr=arrIndxIn->getConstPointer();
11130 int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
11131 std::vector<int> idsToFetch1(seedBg,seedEnd);
11132 std::vector<int> idsToFetch2;
11133 std::vector<int> *idsToFetch=&idsToFetch1;
11134 std::vector<int> *idsToFetchOther=&idsToFetch2;
11135 while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
11137 for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
11138 for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
11140 { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
11141 std::swap(idsToFetch,idsToFetchOther);
11142 idsToFetchOther->clear();
11143 nbOfDepthPeelingPerformed++;
11145 int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
11147 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
11148 int *retPtr=ret->getPointer();
11149 for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
11156 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11157 * 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
11158 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11159 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11161 * \param [in] start begin of set of ids of the input extraction (included)
11162 * \param [in] end end of set of ids of the input extraction (excluded)
11163 * \param [in] step step of the set of ids in range mode.
11164 * \param [in] arrIn arr origin array from which the extraction will be done.
11165 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11166 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11167 * \param [in] srcArrIndex index array of \b srcArr
11168 * \param [out] arrOut the resulting array
11169 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11171 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
11173 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11174 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11175 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11177 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11178 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
11179 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
11180 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
11181 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11183 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11184 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11185 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
11187 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11189 if(it>=0 && it<nbOfTuples)
11190 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
11193 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11194 throw INTERP_KERNEL::Exception(oss.str().c_str());
11197 srcArrIndexPtr=srcArrIndex->getConstPointer();
11198 arrIo->alloc(nbOfTuples+1,1);
11199 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11200 const int *arrInPtr=arrIn->getConstPointer();
11201 const int *srcArrPtr=srcArr->getConstPointer();
11202 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11203 int *arroPtr=arro->getPointer();
11204 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11206 int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
11209 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11210 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11214 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11215 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11218 arrOut=arro.retn();
11219 arrIndexOut=arrIo.retn();
11223 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11224 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11226 * \param [in] start begin of set of ids of the input extraction (included)
11227 * \param [in] end end of set of ids of the input extraction (excluded)
11228 * \param [in] step step of the set of ids in range mode.
11229 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11230 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11231 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11232 * \param [in] srcArrIndex index array of \b srcArr
11234 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11236 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11237 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11239 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11240 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
11241 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11242 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11243 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11244 int *arrInOutPtr=arrInOut->getPointer();
11245 const int *srcArrPtr=srcArr->getConstPointer();
11246 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
11248 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11250 if(it>=0 && it<nbOfTuples)
11252 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
11253 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
11256 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
11257 throw INTERP_KERNEL::Exception(oss.str().c_str());
11262 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11263 throw INTERP_KERNEL::Exception(oss.str().c_str());
11269 * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
11270 * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
11271 * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
11272 * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
11273 * The sum of measure field of returned mesh is equal to the sum of measure field of this.
11275 * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
11277 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
11279 checkFullyDefined();
11280 int mdim=getMeshDimension();
11281 int spaceDim=getSpaceDimension();
11283 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
11284 std::vector<DataArrayInt *> partition=partitionBySpreadZone();
11285 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
11286 std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
11287 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
11288 ret->setCoords(getCoords());
11289 ret->allocateCells((int)partition.size());
11291 for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
11293 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
11294 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
11298 cell=tmp->buildUnionOf2DMesh();
11301 cell=tmp->buildUnionOf3DMesh();
11304 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
11307 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
11310 ret->finishInsertingCells();
11315 * This method partitions \b this into contiguous zone.
11316 * This method only needs a well defined connectivity. Coordinates are not considered here.
11317 * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
11319 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
11321 int nbOfCellsCur=getNumberOfCells();
11322 std::vector<DataArrayInt *> ret;
11323 if(nbOfCellsCur<=0)
11325 DataArrayInt *neigh=0,*neighI=0;
11326 computeNeighborsOfCells(neigh,neighI);
11327 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
11328 std::vector<bool> fetchedCells(nbOfCellsCur,false);
11329 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
11331 while(seed<nbOfCellsCur)
11333 int nbOfPeelPerformed=0;
11334 ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
11335 seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
11337 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
11338 ret.push_back((*it).retn());
11343 * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
11344 * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
11346 * \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.
11347 * \return a newly allocated DataArrayInt to be managed by the caller.
11348 * \throw In case of \a code has not the right format (typically of size 3*n)
11350 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
11352 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
11353 std::size_t nb=code.size()/3;
11354 if(code.size()%3!=0)
11355 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
11356 ret->alloc((int)nb,2);
11357 int *retPtr=ret->getPointer();
11358 for(std::size_t i=0;i<nb;i++,retPtr+=2)
11360 retPtr[0]=code[3*i+2];
11361 retPtr[1]=code[3*i+2]+code[3*i+1];
11367 * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
11368 * All cells in \a this are expected to be linear 3D cells.
11369 * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
11370 * It leads to an increase to number of cells.
11371 * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
11372 * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints
11373 * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
11375 * \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.
11376 * For all other cells, the splitting policy will be ignored. See INTERP_KERNEL::SplittingPolicy for the images.
11377 * \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.
11378 * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
11379 * an id of old cell producing it. The caller is to delete this array using
11380 * decrRef() as it is no more needed.
11381 * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
11383 * \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
11384 * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
11386 * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
11387 * \throw If \a this is not fully constituted with linear 3D cells.
11388 * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
11390 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
11392 INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
11393 checkConnectivityFullyDefined();
11394 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
11395 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
11396 int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
11397 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
11398 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
11399 int *retPt(ret->getPointer());
11400 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
11401 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
11402 const int *oldc(_nodal_connec->begin());
11403 const int *oldci(_nodal_connec_index->begin());
11404 const double *coords(_coords->begin());
11405 for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
11407 std::vector<int> a; std::vector<double> b;
11408 INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
11409 std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
11410 const int *aa(&a[0]);
11413 for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
11415 *it=(-(*(it))-1+nbNodes);
11416 addPts->insertAtTheEnd(b.begin(),b.end());
11417 nbNodes+=(int)b.size()/3;
11419 for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
11420 newConn->insertAtTheEnd(aa,aa+4);
11422 if(!addPts->empty())
11424 addPts->rearrange(3);
11425 nbOfAdditionalPoints=addPts->getNumberOfTuples();
11426 addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
11427 ret0->setCoords(addPts);
11431 nbOfAdditionalPoints=0;
11432 ret0->setCoords(getCoords());
11434 ret0->setNodalConnectivity(newConn);
11436 ret->computeOffsets2();
11437 n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
11438 return ret0.retn();
11442 * 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).
11444 * \sa MEDCouplingUMesh::split2DCells
11446 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
11448 checkConnectivityFullyDefined();
11449 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
11450 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11451 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11452 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11453 int prevPosOfCi(ciPtr[0]);
11454 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11456 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
11457 *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
11458 for(int j=0;j<sz;j++)
11460 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
11461 for(int k=0;k<sz2;k++)
11462 *cPtr++=subPtr[offset2+k];
11464 *cPtr++=oldConn[prevPosOfCi+j+2];
11467 prevPosOfCi=ciPtr[1];
11468 ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11471 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
11472 _nodal_connec->decrRef();
11473 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
11476 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11482 int ret(nodesCnter++);
11484 e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
11485 addCoo.insertAtTheEnd(newPt,newPt+2);
11490 int InternalAddPointOriented(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11496 int ret(nodesCnter++);
11498 e->getMiddleOfPointsOriented(coo+2*startId,coo+2*endId,newPt);
11499 addCoo.insertAtTheEnd(newPt,newPt+2);
11507 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)
11510 int trueStart(start>=0?start:nbOfEdges+start);
11511 tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
11512 newConnOfCell->insertAtTheEnd(tmp,tmp+3);
11517 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11518 InternalAddPointOriented(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
11519 middles.push_back(tmp3+offset);
11522 middles.push_back(connBg[trueStart+nbOfEdges]);
11526 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)
11528 int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
11529 newConnOfCell->pushBackSilent(tmpEnd);
11534 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11535 InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11536 middles.push_back(tmp3+offset);
11539 middles.push_back(connBg[start+nbOfEdges]);
11543 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)
11545 // only the quadratic point to deal with:
11550 int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
11551 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11552 InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11553 middles.push_back(tmp3+offset);
11556 middles.push_back(connBg[start+nbOfEdges]);
11563 * 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 ) .
11564 * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
11566 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
11568 std::size_t sz(std::distance(connBg,connEnd));
11569 if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
11570 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
11572 INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
11573 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
11574 unsigned nbs(cm.getNumberOfSons2(connBg+1,sz));
11575 unsigned nbOfHit(0); // number of fusions operated
11576 int posBaseElt(0),posEndElt(0),nbOfTurn(0);
11577 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
11578 INTERP_KERNEL::NormalizedCellType typeOfSon;
11579 std::vector<int> middles;
11581 for(;(nbOfTurn+nbOfHit)<nbs;nbOfTurn++)
11583 cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
11584 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
11585 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11586 posEndElt = posBaseElt+1;
11588 // Look backward first: are the final edges of the cells colinear with the first ones?
11589 // This initializes posBaseElt.
11592 for(unsigned i=1;i<nbs && nbOfHit<maxNbOfHit;i++) // 2nd condition is to avoid ending with a cell wih one single edge
11594 cm.fillSonCellNodalConnectivity2(nbs-i,connBg+1,sz,tmpConn,typeOfSon);
11595 INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11596 INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11597 bool isColinear=eint->areColinears();
11610 // Now move forward:
11611 const unsigned fwdStart = (nbOfTurn == 0 ? 0 : posBaseElt); // the first element to be inspected going forward
11612 for(unsigned j=fwdStart+1;j<nbs && nbOfHit<maxNbOfHit;j++) // 2nd condition is to avoid ending with a cell wih one single edge
11614 cm.fillSonCellNodalConnectivity2((int)j,connBg+1,sz,tmpConn,typeOfSon); // get edge #j's connectivity
11615 INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11616 INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11617 bool isColinear(eint->areColinears());
11629 //push [posBaseElt,posEndElt) in newConnOfCell using e
11630 // 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!
11632 // at the begining of the connectivity (insert type)
11633 EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11634 else if((nbOfHit+nbOfTurn) != (nbs-1))
11636 EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11637 if ((nbOfHit+nbOfTurn) == (nbs-1))
11638 // at the end (only quad points to deal with)
11639 EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11640 posBaseElt=posEndElt;
11643 if(!middles.empty())
11644 newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
11649 * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
11651 * \return int - the number of new nodes created.
11652 * \sa MEDCouplingUMesh::split2DCells
11654 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
11657 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
11658 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11659 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
11660 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11661 const int *midPtr(mid->begin()),*midIPtr(midI->begin());
11662 const double *oldCoordsPtr(getCoords()->begin());
11663 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11664 int prevPosOfCi(ciPtr[0]);
11665 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11667 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
11668 for(int j=0;j<sz;j++)
11669 { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
11670 *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
11671 for(int j=0;j<sz;j++)//loop over subedges of oldConn
11673 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
11677 cPtr[1]=oldConn[prevPosOfCi+2+j];
11678 cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
11681 std::vector<INTERP_KERNEL::Node *> ns(3);
11682 ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
11683 ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
11684 ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
11685 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
11686 for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
11688 cPtr[1]=subPtr[offset2+k];
11689 cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
11691 int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
11693 { cPtr[1]=tmpEnd; }
11694 cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
11696 prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
11697 ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11700 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
11701 _nodal_connec->decrRef();
11702 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
11703 addCoo->rearrange(2);
11704 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
11706 return addCoo->getNumberOfTuples();
11709 void MEDCouplingUMesh::ComputeAllTypesInternal(std::set<INTERP_KERNEL::NormalizedCellType>& types, const DataArrayInt *nodalConnec, const DataArrayInt *nodalConnecIndex)
11711 if(nodalConnec && nodalConnecIndex)
11714 const int *conn(nodalConnec->getConstPointer()),*connIndex(nodalConnecIndex->getConstPointer());
11715 int nbOfElem(nodalConnecIndex->getNbOfElems()-1);
11717 for(const int *pt=connIndex;pt!=connIndex+nbOfElem;pt++)
11718 types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
11722 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
11723 _own_cell(true),_cell_id(-1),_nb_cell(0)
11728 _nb_cell=mesh->getNumberOfCells();
11732 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
11740 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
11741 _own_cell(false),_cell_id(bg-1),
11748 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
11751 if(_cell_id<_nb_cell)
11760 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
11766 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
11768 return new MEDCouplingUMeshCellByTypeIterator(_mesh);
11771 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
11777 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
11785 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
11791 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
11796 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
11801 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
11803 return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
11806 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
11811 _nb_cell=mesh->getNumberOfCells();
11815 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
11822 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
11824 const int *c=_mesh->getNodalConnectivity()->getConstPointer();
11825 const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
11826 if(_cell_id<_nb_cell)
11828 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
11829 int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
11830 int startId=_cell_id;
11831 _cell_id+=nbOfElems;
11832 return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
11838 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
11842 _conn=mesh->getNodalConnectivity()->getPointer();
11843 _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
11847 void MEDCouplingUMeshCell::next()
11849 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11854 _conn_lgth=_conn_indx[1]-_conn_indx[0];
11857 std::string MEDCouplingUMeshCell::repr() const
11859 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11861 std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
11863 std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
11867 return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
11870 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
11872 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11873 return (INTERP_KERNEL::NormalizedCellType)_conn[0];
11875 return INTERP_KERNEL::NORM_ERROR;
11878 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
11881 if(_conn_lgth!=NOTICABLE_FIRST_VAL)