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);
2493 // For each initial connex part of the sub-mesh (or said differently for each independent crack):
2494 int seed = 0, nIter = 0;
2495 int nIterMax = nCells2+1; // Safety net for the loop
2496 std::vector<bool> hitCells(nCells2);
2497 hitCells.assign(nCells2, false);
2498 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum = DataArrayInt::New();
2499 cellsToModifyConn0_torenum->alloc(0,1);
2500 while (nIter < nIterMax)
2502 if (std::find(hitCells.begin(), hitCells.end(), false) == hitCells.end())
2504 // Connex zone without the crack (to compute the next seed really)
2506 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connexCheck = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neighInit00,neighIInit00, -1, dnu);
2508 for (int * ptr = connexCheck->getPointer(); cnt < connexCheck->getNumberOfTuples(); ptr++, cnt++)
2509 hitCells[*ptr] = true;
2510 // Connex zone WITH the crack (to identify cells lying on either part of the crack)
2511 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> spreadZone = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neigh00,neighI00, -1, dnu);
2512 cellsToModifyConn0_torenum = DataArrayInt::Aggregate(cellsToModifyConn0_torenum, spreadZone, 0);
2513 // Compute next seed, i.e. a cell in another connex part:
2514 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comple = cellsToModifyConn0_torenum->buildComplement(nCells2);
2515 seed = comple->getIJ(0,0);
2518 if (nIter >= nIterMax)
2519 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate(): internal error - too many iterations.");
2521 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2522 cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2523 cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2525 cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2526 cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2527 nodeIdsToDuplicate=s3.retn();
2531 * This method operates a modification of the connectivity and coords in \b this.
2532 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2533 * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2534 * 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
2535 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2536 * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2538 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2540 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2541 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2543 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2545 int nbOfNodes=getNumberOfNodes();
2546 duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2547 duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2551 * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of
2552 * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range !
2554 * \param [in] offset - specifies the offset to be applied on each element of connectivity.
2556 * \sa renumberNodesInConn
2558 void MEDCouplingUMesh::renumberNodesWithOffsetInConn(int offset)
2560 checkConnectivityFullyDefined();
2561 int *conn(getNodalConnectivity()->getPointer());
2562 const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2563 int nbOfCells(getNumberOfCells());
2564 for(int i=0;i<nbOfCells;i++)
2565 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2567 int& node=conn[iconn];
2568 if(node>=0)//avoid polyhedron separator
2573 _nodal_connec->declareAsNew();
2578 * Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
2579 * 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
2582 void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& newNodeNumbersO2N)
2584 checkConnectivityFullyDefined();
2585 int *conn(getNodalConnectivity()->getPointer());
2586 const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2587 int nbOfCells(getNumberOfCells());
2588 for(int i=0;i<nbOfCells;i++)
2589 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2591 int& node=conn[iconn];
2592 if(node>=0)//avoid polyhedron separator
2594 INTERP_KERNEL::HashMap<int,int>::const_iterator it(newNodeNumbersO2N.find(node));
2595 if(it!=newNodeNumbersO2N.end())
2601 std::ostringstream oss; oss << "MEDCouplingUMesh::renumberNodesInConn(map) : presence in connectivity for cell #" << i << " of node #" << node << " : Not in map !";
2602 throw INTERP_KERNEL::Exception(oss.str().c_str());
2606 _nodal_connec->declareAsNew();
2611 * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2612 * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2613 * This method is a generalization of shiftNodeNumbersInConn().
2614 * \warning This method performs no check of validity of new ids. **Use it with care !**
2615 * \param [in] newNodeNumbersO2N - a permutation array, of length \a
2616 * this->getNumberOfNodes(), in "Old to New" mode.
2617 * See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2618 * \throw If the nodal connectivity of cells is not defined.
2620 * \if ENABLE_EXAMPLES
2621 * \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2622 * \ref py_mcumesh_renumberNodesInConn "Here is a Python example".
2625 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2627 checkConnectivityFullyDefined();
2628 int *conn=getNodalConnectivity()->getPointer();
2629 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2630 int nbOfCells(getNumberOfCells());
2631 for(int i=0;i<nbOfCells;i++)
2632 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2634 int& node=conn[iconn];
2635 if(node>=0)//avoid polyhedron separator
2637 node=newNodeNumbersO2N[node];
2640 _nodal_connec->declareAsNew();
2645 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2646 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2647 * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2649 * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2651 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2653 checkConnectivityFullyDefined();
2654 int *conn=getNodalConnectivity()->getPointer();
2655 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2656 int nbOfCells=getNumberOfCells();
2657 for(int i=0;i<nbOfCells;i++)
2658 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2660 int& node=conn[iconn];
2661 if(node>=0)//avoid polyhedron separator
2666 _nodal_connec->declareAsNew();
2671 * This method operates a modification of the connectivity in \b this.
2672 * 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.
2673 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2674 * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2675 * 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
2676 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2677 * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2679 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2680 * As an another consequense after the call of this method \b this can be transiently non cohrent.
2682 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2683 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2684 * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ).
2686 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2688 checkConnectivityFullyDefined();
2689 std::map<int,int> m;
2691 for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2693 int *conn=getNodalConnectivity()->getPointer();
2694 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2695 int nbOfCells=getNumberOfCells();
2696 for(int i=0;i<nbOfCells;i++)
2697 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2699 int& node=conn[iconn];
2700 if(node>=0)//avoid polyhedron separator
2702 std::map<int,int>::iterator it=m.find(node);
2711 * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2713 * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2714 * After the call of this method the number of cells remains the same as before.
2716 * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2717 * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2718 * be strictly in [0;this->getNumberOfCells()).
2720 * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2721 * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2722 * should be contained in[0;this->getNumberOfCells()).
2724 * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2726 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2728 checkConnectivityFullyDefined();
2729 int nbCells=getNumberOfCells();
2730 const int *array=old2NewBg;
2732 array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2734 const int *conn=_nodal_connec->getConstPointer();
2735 const int *connI=_nodal_connec_index->getConstPointer();
2736 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2737 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2738 const int *n2oPtr=n2o->begin();
2739 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2740 newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2741 newConn->copyStringInfoFrom(*_nodal_connec);
2742 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2743 newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2744 newConnI->copyStringInfoFrom(*_nodal_connec_index);
2746 int *newC=newConn->getPointer();
2747 int *newCI=newConnI->getPointer();
2750 for(int i=0;i<nbCells;i++)
2753 int nbOfElts=connI[pos+1]-connI[pos];
2754 newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2759 setConnectivity(newConn,newConnI);
2761 free(const_cast<int *>(array));
2765 * Finds cells whose bounding boxes intersect a given bounding box.
2766 * \param [in] bbox - an array defining the bounding box via coordinates of its
2767 * extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2769 * \param [in] eps - a factor used to increase size of the bounding box of cell
2770 * before comparing it with \a bbox. This factor is multiplied by the maximal
2771 * extent of the bounding box of cell to produce an addition to this bounding box.
2772 * \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2773 * cells. The caller is to delete this array using decrRef() as it is no more
2775 * \throw If the coordinates array is not set.
2776 * \throw If the nodal connectivity of cells is not defined.
2778 * \if ENABLE_EXAMPLES
2779 * \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2780 * \ref py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2783 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2785 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2786 if(getMeshDimension()==-1)
2788 elems->pushBackSilent(0);
2789 return elems.retn();
2791 int dim=getSpaceDimension();
2792 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2793 const int* conn = getNodalConnectivity()->getConstPointer();
2794 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2795 const double* coords = getCoords()->getConstPointer();
2796 int nbOfCells=getNumberOfCells();
2797 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2799 for (int i=0; i<dim; i++)
2801 elem_bb[i*2]=std::numeric_limits<double>::max();
2802 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2805 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2807 int node= conn[inode];
2808 if(node>=0)//avoid polyhedron separator
2810 for (int idim=0; idim<dim; idim++)
2812 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2814 elem_bb[idim*2] = coords[node*dim+idim] ;
2816 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2818 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2823 if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2824 elems->pushBackSilent(ielem);
2826 return elems.retn();
2830 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2831 * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2832 * added in 'elems' parameter.
2834 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2836 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2837 if(getMeshDimension()==-1)
2839 elems->pushBackSilent(0);
2840 return elems.retn();
2842 int dim=getSpaceDimension();
2843 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2844 const int* conn = getNodalConnectivity()->getConstPointer();
2845 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2846 const double* coords = getCoords()->getConstPointer();
2847 int nbOfCells=getNumberOfCells();
2848 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2850 for (int i=0; i<dim; i++)
2852 elem_bb[i*2]=std::numeric_limits<double>::max();
2853 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2856 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2858 int node= conn[inode];
2859 if(node>=0)//avoid polyhedron separator
2861 for (int idim=0; idim<dim; idim++)
2863 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2865 elem_bb[idim*2] = coords[node*dim+idim] ;
2867 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2869 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2874 if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2875 elems->pushBackSilent(ielem);
2877 return elems.retn();
2881 * Returns a type of a cell by its id.
2882 * \param [in] cellId - the id of the cell of interest.
2883 * \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2884 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2886 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2888 const int *ptI=_nodal_connec_index->getConstPointer();
2889 const int *pt=_nodal_connec->getConstPointer();
2890 if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2891 return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2894 std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2895 throw INTERP_KERNEL::Exception(oss.str().c_str());
2900 * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2901 * This method does not throw exception if geometric type \a type is not in \a this.
2902 * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2903 * The coordinates array is not considered here.
2905 * \param [in] type the geometric type
2906 * \return cell ids in this having geometric type \a type.
2908 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2911 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2913 checkConnectivityFullyDefined();
2914 int nbCells=getNumberOfCells();
2915 int mdim=getMeshDimension();
2916 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2917 if(mdim!=(int)cm.getDimension())
2918 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2919 const int *ptI=_nodal_connec_index->getConstPointer();
2920 const int *pt=_nodal_connec->getConstPointer();
2921 for(int i=0;i<nbCells;i++)
2923 if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2924 ret->pushBackSilent(i);
2930 * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2932 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2934 const int *ptI=_nodal_connec_index->getConstPointer();
2935 const int *pt=_nodal_connec->getConstPointer();
2936 int nbOfCells=getNumberOfCells();
2938 for(int i=0;i<nbOfCells;i++)
2939 if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2945 * Returns the nodal connectivity of a given cell.
2946 * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2947 * all returned node ids can be used in getCoordinatesOfNode().
2948 * \param [in] cellId - an id of the cell of interest.
2949 * \param [in,out] conn - a vector where the node ids are appended. It is not
2950 * cleared before the appending.
2951 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2953 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2955 const int *ptI=_nodal_connec_index->getConstPointer();
2956 const int *pt=_nodal_connec->getConstPointer();
2957 for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2962 std::string MEDCouplingUMesh::simpleRepr() const
2964 static const char msg0[]="No coordinates specified !";
2965 std::ostringstream ret;
2966 ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2967 ret << "Description of mesh : \"" << getDescription() << "\"\n";
2969 double tt=getTime(tmpp1,tmpp2);
2970 ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2971 ret << "Iteration : " << tmpp1 << " Order : " << tmpp2 << "\n";
2973 { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2975 { ret << " Mesh dimension has not been set or is invalid !"; }
2978 const int spaceDim=getSpaceDimension();
2979 ret << spaceDim << "\nInfo attached on space dimension : ";
2980 for(int i=0;i<spaceDim;i++)
2981 ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2985 ret << msg0 << "\n";
2986 ret << "Number of nodes : ";
2988 ret << getNumberOfNodes() << "\n";
2990 ret << msg0 << "\n";
2991 ret << "Number of cells : ";
2992 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2993 ret << getNumberOfCells() << "\n";
2995 ret << "No connectivity specified !" << "\n";
2996 ret << "Cell types present : ";
2997 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2999 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
3000 ret << cm.getRepr() << " ";
3006 std::string MEDCouplingUMesh::advancedRepr() const
3008 std::ostringstream ret;
3009 ret << simpleRepr();
3010 ret << "\nCoordinates array : \n___________________\n\n";
3012 _coords->reprWithoutNameStream(ret);
3014 ret << "No array set !\n";
3015 ret << "\n\nConnectivity arrays : \n_____________________\n\n";
3016 reprConnectivityOfThisLL(ret);
3021 * This method returns a C++ code that is a dump of \a this.
3022 * This method will throw if this is not fully defined.
3024 std::string MEDCouplingUMesh::cppRepr() const
3026 static const char coordsName[]="coords";
3027 static const char connName[]="conn";
3028 static const char connIName[]="connI";
3029 checkFullyDefined();
3030 std::ostringstream ret; ret << "// coordinates" << std::endl;
3031 _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
3032 _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
3033 _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
3034 ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
3035 ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
3036 ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
3037 ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
3041 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
3043 std::ostringstream ret;
3044 reprConnectivityOfThisLL(ret);
3049 * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
3050 * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
3051 * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
3054 * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
3055 * 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
3056 * with number of tuples set to 0, if not the array is taken as this in the returned instance.
3058 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
3060 int mdim=getMeshDimension();
3062 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
3063 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
3064 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
3065 bool needToCpyCT=true;
3068 tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
3076 if(!_nodal_connec_index)
3078 tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
3083 tmp2=_nodal_connec_index;
3086 ret->setConnectivity(tmp1,tmp2,false);
3091 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
3092 ret->setCoords(coords);
3095 ret->setCoords(_coords);
3099 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
3101 if(_nodal_connec!=0 && _nodal_connec_index!=0)
3103 int nbOfCells=getNumberOfCells();
3104 const int *c=_nodal_connec->getConstPointer();
3105 const int *ci=_nodal_connec_index->getConstPointer();
3106 for(int i=0;i<nbOfCells;i++)
3108 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3109 stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3110 std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3115 stream << "Connectivity not defined !\n";
3118 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3120 const int *ptI=_nodal_connec_index->getConstPointer();
3121 const int *pt=_nodal_connec->getConstPointer();
3122 if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3123 return ptI[cellId+1]-ptI[cellId]-1;
3125 return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3129 * Returns types of cells of the specified part of \a this mesh.
3130 * This method avoids computing sub-mesh explicitely to get its types.
3131 * \param [in] begin - an array of cell ids of interest.
3132 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3133 * \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3134 * describing the cell types.
3135 * \throw If the coordinates array is not set.
3136 * \throw If the nodal connectivity of cells is not defined.
3137 * \sa getAllGeoTypes()
3139 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3141 checkFullyDefined();
3142 std::set<INTERP_KERNEL::NormalizedCellType> ret;
3143 const int *conn=_nodal_connec->getConstPointer();
3144 const int *connIndex=_nodal_connec_index->getConstPointer();
3145 for(const int *w=begin;w!=end;w++)
3146 ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3151 * Defines the nodal connectivity using given connectivity arrays. Optionally updates
3152 * a set of types of cells constituting \a this mesh.
3153 * This method is for advanced users having prepared their connectivity before. For
3154 * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3155 * \param [in] conn - the nodal connectivity array.
3156 * \param [in] connIndex - the nodal connectivity index array.
3157 * \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3160 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3162 DataArrayInt::SetArrayIn(conn,_nodal_connec);
3163 DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3164 if(isComputingTypes)
3170 * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
3171 * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3173 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3174 _nodal_connec(0),_nodal_connec_index(0),
3175 _types(other._types)
3177 if(other._nodal_connec)
3178 _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3179 if(other._nodal_connec_index)
3180 _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3183 MEDCouplingUMesh::~MEDCouplingUMesh()
3186 _nodal_connec->decrRef();
3187 if(_nodal_connec_index)
3188 _nodal_connec_index->decrRef();
3192 * Recomputes a set of cell types of \a this mesh. For more info see
3193 * \ref MEDCouplingUMeshNodalConnectivity.
3195 void MEDCouplingUMesh::computeTypes()
3197 ComputeAllTypesInternal(_types,_nodal_connec,_nodal_connec_index);
3201 * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3203 void MEDCouplingUMesh::checkFullyDefined() const
3205 if(!_nodal_connec_index || !_nodal_connec || !_coords)
3206 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3210 * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3212 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3214 if(!_nodal_connec_index || !_nodal_connec)
3215 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3219 * Returns a number of cells constituting \a this mesh.
3220 * \return int - the number of cells in \a this mesh.
3221 * \throw If the nodal connectivity of cells is not defined.
3223 int MEDCouplingUMesh::getNumberOfCells() const
3225 if(_nodal_connec_index)
3226 return _nodal_connec_index->getNumberOfTuples()-1;
3231 throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3235 * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3236 * mesh. For more info see \ref MEDCouplingMeshesPage.
3237 * \return int - the dimension of \a this mesh.
3238 * \throw If the mesh dimension is not defined using setMeshDimension().
3240 int MEDCouplingUMesh::getMeshDimension() const
3243 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3248 * Returns a length of the nodal connectivity array.
3249 * This method is for test reason. Normally the integer returned is not useable by
3250 * user. For more info see \ref MEDCouplingUMeshNodalConnectivity.
3251 * \return int - the length of the nodal connectivity array.
3253 int MEDCouplingUMesh::getMeshLength() const
3255 return _nodal_connec->getNbOfElems();
3259 * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3261 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3263 MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3264 tinyInfo.push_back(getMeshDimension());
3265 tinyInfo.push_back(getNumberOfCells());
3267 tinyInfo.push_back(getMeshLength());
3269 tinyInfo.push_back(-1);
3273 * First step of unserialization process.
3275 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3277 return tinyInfo[6]<=0;
3281 * Second step of serialization process.
3282 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3284 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3286 MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3288 a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3292 * Third and final step of serialization process.
3294 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3296 MEDCouplingPointSet::serialize(a1,a2);
3297 if(getMeshDimension()>-1)
3299 a1=DataArrayInt::New();
3300 a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3301 int *ptA1=a1->getPointer();
3302 const int *conn=getNodalConnectivity()->getConstPointer();
3303 const int *index=getNodalConnectivityIndex()->getConstPointer();
3304 ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3305 std::copy(conn,conn+getMeshLength(),ptA1);
3312 * Second and final unserialization process.
3313 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3315 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3317 MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3318 setMeshDimension(tinyInfo[5]);
3322 const int *recvBuffer=a1->getConstPointer();
3323 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3324 myConnecIndex->alloc(tinyInfo[6]+1,1);
3325 std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3326 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3327 myConnec->alloc(tinyInfo[7],1);
3328 std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3329 setConnectivity(myConnec, myConnecIndex);
3334 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3335 * CellIds are given using range specified by a start an end and step.
3337 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3339 checkFullyDefined();
3340 int ncell=getNumberOfCells();
3341 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3342 ret->_mesh_dim=_mesh_dim;
3343 ret->setCoords(_coords);
3344 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3345 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3346 int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3348 const int *conn=_nodal_connec->getConstPointer();
3349 const int *connIndex=_nodal_connec_index->getConstPointer();
3350 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3352 if(work>=0 && work<ncell)
3354 newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3358 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3359 throw INTERP_KERNEL::Exception(oss.str().c_str());
3362 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3363 int *newConnPtr=newConn->getPointer();
3364 std::set<INTERP_KERNEL::NormalizedCellType> types;
3366 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3368 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3369 newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3371 ret->setConnectivity(newConn,newConnI,false);
3373 ret->copyTinyInfoFrom(this);
3378 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3379 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3380 * The return newly allocated mesh will share the same coordinates as \a this.
3382 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3384 checkConnectivityFullyDefined();
3385 int ncell=getNumberOfCells();
3386 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3387 ret->_mesh_dim=_mesh_dim;
3388 ret->setCoords(_coords);
3389 std::size_t nbOfElemsRet=std::distance(begin,end);
3390 int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3392 const int *conn=_nodal_connec->getConstPointer();
3393 const int *connIndex=_nodal_connec_index->getConstPointer();
3395 for(const int *work=begin;work!=end;work++,newNbring++)
3397 if(*work>=0 && *work<ncell)
3398 connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3402 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3403 throw INTERP_KERNEL::Exception(oss.str().c_str());
3406 int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3407 int *connRetWork=connRet;
3408 std::set<INTERP_KERNEL::NormalizedCellType> types;
3409 for(const int *work=begin;work!=end;work++)
3411 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3412 connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3414 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3415 connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3416 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3417 connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3418 ret->setConnectivity(connRetArr,connIndexRetArr,false);
3420 ret->copyTinyInfoFrom(this);
3425 * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3427 * For 1D cells, the returned field contains lengths.<br>
3428 * For 2D cells, the returned field contains areas.<br>
3429 * For 3D cells, the returned field contains volumes.
3430 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3431 * orientation, i.e. the volume is always positive.
3432 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3433 * and one time . The caller is to delete this field using decrRef() as it is no
3436 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3438 std::string name="MeasureOfMesh_";
3440 int nbelem=getNumberOfCells();
3441 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3442 field->setName(name);
3443 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3444 array->alloc(nbelem,1);
3445 double *area_vol=array->getPointer();
3446 field->setArray(array) ; array=0;
3447 field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3448 field->synchronizeTimeWithMesh();
3449 if(getMeshDimension()!=-1)
3452 INTERP_KERNEL::NormalizedCellType type;
3453 int dim_space=getSpaceDimension();
3454 const double *coords=getCoords()->getConstPointer();
3455 const int *connec=getNodalConnectivity()->getConstPointer();
3456 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3457 for(int iel=0;iel<nbelem;iel++)
3459 ipt=connec_index[iel];
3460 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3461 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);
3464 std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3468 area_vol[0]=std::numeric_limits<double>::max();
3470 return field.retn();
3474 * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3476 * For 1D cells, the returned array contains lengths.<br>
3477 * For 2D cells, the returned array contains areas.<br>
3478 * For 3D cells, the returned array contains volumes.
3479 * This method avoids building explicitly a part of \a this mesh to perform the work.
3480 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3481 * orientation, i.e. the volume is always positive.
3482 * \param [in] begin - an array of cell ids of interest.
3483 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3484 * \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3485 * delete this array using decrRef() as it is no more needed.
3487 * \if ENABLE_EXAMPLES
3488 * \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3489 * \ref py_mcumesh_getPartMeasureField "Here is a Python example".
3491 * \sa getMeasureField()
3493 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3495 std::string name="PartMeasureOfMesh_";
3497 int nbelem=(int)std::distance(begin,end);
3498 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3499 array->setName(name);
3500 array->alloc(nbelem,1);
3501 double *area_vol=array->getPointer();
3502 if(getMeshDimension()!=-1)
3505 INTERP_KERNEL::NormalizedCellType type;
3506 int dim_space=getSpaceDimension();
3507 const double *coords=getCoords()->getConstPointer();
3508 const int *connec=getNodalConnectivity()->getConstPointer();
3509 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3510 for(const int *iel=begin;iel!=end;iel++)
3512 ipt=connec_index[*iel];
3513 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3514 *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3517 std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3521 area_vol[0]=std::numeric_limits<double>::max();
3523 return array.retn();
3527 * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3528 * \a this one. The returned field contains the dual cell volume for each corresponding
3529 * node in \a this mesh. In other words, the field returns the getMeasureField() of
3530 * the dual mesh in P1 sens of \a this.<br>
3531 * For 1D cells, the returned field contains lengths.<br>
3532 * For 2D cells, the returned field contains areas.<br>
3533 * For 3D cells, the returned field contains volumes.
3534 * This method is useful to check "P1*" conservative interpolators.
3535 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3536 * orientation, i.e. the volume is always positive.
3537 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3538 * nodes and one time. The caller is to delete this array using decrRef() as
3539 * it is no more needed.
3541 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3543 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3544 std::string name="MeasureOnNodeOfMesh_";
3546 int nbNodes=getNumberOfNodes();
3547 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3548 double cst=1./((double)getMeshDimension()+1.);
3549 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3550 array->alloc(nbNodes,1);
3551 double *valsToFill=array->getPointer();
3552 std::fill(valsToFill,valsToFill+nbNodes,0.);
3553 const double *values=tmp->getArray()->getConstPointer();
3554 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3555 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3556 getReverseNodalConnectivity(da,daInd);
3557 const int *daPtr=da->getConstPointer();
3558 const int *daIPtr=daInd->getConstPointer();
3559 for(int i=0;i<nbNodes;i++)
3560 for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3561 valsToFill[i]+=cst*values[*cell];
3563 ret->setArray(array);
3568 * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3569 * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3570 * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3571 * and are normalized.
3572 * <br> \a this can be either
3573 * - a 2D mesh in 2D or 3D space or
3574 * - an 1D mesh in 2D space.
3576 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3577 * cells and one time. The caller is to delete this field using decrRef() as
3578 * it is no more needed.
3579 * \throw If the nodal connectivity of cells is not defined.
3580 * \throw If the coordinates array is not set.
3581 * \throw If the mesh dimension is not set.
3582 * \throw If the mesh and space dimension is not as specified above.
3584 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3586 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3587 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3588 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3589 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3590 int nbOfCells=getNumberOfCells();
3591 int nbComp=getMeshDimension()+1;
3592 array->alloc(nbOfCells,nbComp);
3593 double *vals=array->getPointer();
3594 const int *connI=_nodal_connec_index->getConstPointer();
3595 const int *conn=_nodal_connec->getConstPointer();
3596 const double *coords=_coords->getConstPointer();
3597 if(getMeshDimension()==2)
3599 if(getSpaceDimension()==3)
3601 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3602 const double *locPtr=loc->getConstPointer();
3603 for(int i=0;i<nbOfCells;i++,vals+=3)
3605 int offset=connI[i];
3606 INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3607 double n=INTERP_KERNEL::norm<3>(vals);
3608 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3613 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3614 const double *isAbsPtr=isAbs->getArray()->begin();
3615 for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3616 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3619 else//meshdimension==1
3622 for(int i=0;i<nbOfCells;i++)
3624 int offset=connI[i];
3625 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3626 double n=INTERP_KERNEL::norm<2>(tmp);
3627 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3632 ret->setArray(array);
3634 ret->synchronizeTimeWithSupport();
3639 * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3640 * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3641 * and are normalized.
3642 * <br> \a this can be either
3643 * - a 2D mesh in 2D or 3D space or
3644 * - an 1D mesh in 2D space.
3646 * This method avoids building explicitly a part of \a this mesh to perform the work.
3647 * \param [in] begin - an array of cell ids of interest.
3648 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3649 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3650 * cells and one time. The caller is to delete this field using decrRef() as
3651 * it is no more needed.
3652 * \throw If the nodal connectivity of cells is not defined.
3653 * \throw If the coordinates array is not set.
3654 * \throw If the mesh dimension is not set.
3655 * \throw If the mesh and space dimension is not as specified above.
3656 * \sa buildOrthogonalField()
3658 * \if ENABLE_EXAMPLES
3659 * \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3660 * \ref py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3663 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3665 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3666 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3667 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3668 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3669 std::size_t nbelems=std::distance(begin,end);
3670 int nbComp=getMeshDimension()+1;
3671 array->alloc((int)nbelems,nbComp);
3672 double *vals=array->getPointer();
3673 const int *connI=_nodal_connec_index->getConstPointer();
3674 const int *conn=_nodal_connec->getConstPointer();
3675 const double *coords=_coords->getConstPointer();
3676 if(getMeshDimension()==2)
3678 if(getSpaceDimension()==3)
3680 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3681 const double *locPtr=loc->getConstPointer();
3682 for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3684 int offset=connI[*i];
3685 INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3686 double n=INTERP_KERNEL::norm<3>(vals);
3687 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3692 for(std::size_t i=0;i<nbelems;i++)
3693 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3696 else//meshdimension==1
3699 for(const int *i=begin;i!=end;i++)
3701 int offset=connI[*i];
3702 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3703 double n=INTERP_KERNEL::norm<2>(tmp);
3704 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3709 ret->setArray(array);
3711 ret->synchronizeTimeWithSupport();
3716 * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3717 * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3718 * and are \b not normalized.
3719 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3720 * cells and one time. The caller is to delete this field using decrRef() as
3721 * it is no more needed.
3722 * \throw If the nodal connectivity of cells is not defined.
3723 * \throw If the coordinates array is not set.
3724 * \throw If \a this->getMeshDimension() != 1.
3725 * \throw If \a this mesh includes cells of type other than SEG2.
3727 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3729 if(getMeshDimension()!=1)
3730 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3731 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3732 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3733 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3734 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3735 int nbOfCells=getNumberOfCells();
3736 int spaceDim=getSpaceDimension();
3737 array->alloc(nbOfCells,spaceDim);
3738 double *pt=array->getPointer();
3739 const double *coo=getCoords()->getConstPointer();
3740 std::vector<int> conn;
3742 for(int i=0;i<nbOfCells;i++)
3745 getNodeIdsOfCell(i,conn);
3746 pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3748 ret->setArray(array);
3750 ret->synchronizeTimeWithSupport();
3755 * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3756 * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3757 * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3758 * from. If a result face is shared by two 3D cells, then the face in included twice in
3760 * \param [in] origin - 3 components of a point defining location of the plane.
3761 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3762 * must be greater than 1e-6.
3763 * \param [in] eps - half-thickness of the plane.
3764 * \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3765 * producing correspondent 2D cells. The caller is to delete this array
3766 * using decrRef() as it is no more needed.
3767 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3768 * not share the node coordinates array with \a this mesh. The caller is to
3769 * delete this mesh using decrRef() as it is no more needed.
3770 * \throw If the coordinates array is not set.
3771 * \throw If the nodal connectivity of cells is not defined.
3772 * \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3773 * \throw If magnitude of \a vec is less than 1e-6.
3774 * \throw If the plane does not intersect any 3D cell of \a this mesh.
3775 * \throw If \a this includes quadratic cells.
3777 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3779 checkFullyDefined();
3780 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3781 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3782 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3783 if(candidates->empty())
3784 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3785 std::vector<int> nodes;
3786 DataArrayInt *cellIds1D=0;
3787 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3788 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3789 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3790 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3791 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3792 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3793 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3794 revDesc2=0; revDescIndx2=0;
3795 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3796 revDesc1=0; revDescIndx1=0;
3797 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3798 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3800 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3801 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3803 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3804 std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3805 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3806 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3807 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3808 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3809 connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3810 subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3811 if(cellIds2->empty())
3812 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3813 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3814 ret->setCoords(mDesc1->getCoords());
3815 ret->setConnectivity(conn,connI,true);
3816 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3821 * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3822 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
3823 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3825 * \param [in] origin - 3 components of a point defining location of the plane.
3826 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3827 * must be greater than 1e-6.
3828 * \param [in] eps - half-thickness of the plane.
3829 * \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3830 * producing correspondent segments. The caller is to delete this array
3831 * using decrRef() as it is no more needed.
3832 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3833 * mesh in 3D space. This mesh does not share the node coordinates array with
3834 * \a this mesh. The caller is to delete this mesh using decrRef() as it is
3836 * \throw If the coordinates array is not set.
3837 * \throw If the nodal connectivity of cells is not defined.
3838 * \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3839 * \throw If magnitude of \a vec is less than 1e-6.
3840 * \throw If the plane does not intersect any 2D cell of \a this mesh.
3841 * \throw If \a this includes quadratic cells.
3843 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3845 checkFullyDefined();
3846 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3847 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3848 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3849 if(candidates->empty())
3850 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3851 std::vector<int> nodes;
3852 DataArrayInt *cellIds1D=0;
3853 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3854 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3855 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3856 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3857 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3858 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3859 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3860 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3861 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3863 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3864 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3866 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3867 int ncellsSub=subMesh->getNumberOfCells();
3868 std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3869 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3870 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3871 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3872 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3874 const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3875 const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3876 for(int i=0;i<ncellsSub;i++)
3878 if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3880 if(cut3DSurf[i].first!=-2)
3882 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3883 connI->pushBackSilent(conn->getNumberOfTuples());
3884 cellIds2->pushBackSilent(i);
3888 int cellId3DSurf=cut3DSurf[i].second;
3889 int offset=nodalI[cellId3DSurf]+1;
3890 int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3891 for(int j=0;j<nbOfEdges;j++)
3893 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3894 connI->pushBackSilent(conn->getNumberOfTuples());
3895 cellIds2->pushBackSilent(cellId3DSurf);
3900 if(cellIds2->empty())
3901 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3902 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3903 ret->setCoords(mDesc1->getCoords());
3904 ret->setConnectivity(conn,connI,true);
3905 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3910 * Finds cells whose bounding boxes intersect a given plane.
3911 * \param [in] origin - 3 components of a point defining location of the plane.
3912 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3913 * must be greater than 1e-6.
3914 * \param [in] eps - half-thickness of the plane.
3915 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3916 * cells. The caller is to delete this array using decrRef() as it is no more
3918 * \throw If the coordinates array is not set.
3919 * \throw If the nodal connectivity of cells is not defined.
3920 * \throw If \a this->getSpaceDimension() != 3.
3921 * \throw If magnitude of \a vec is less than 1e-6.
3922 * \sa buildSlice3D()
3924 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3926 checkFullyDefined();
3927 if(getSpaceDimension()!=3)
3928 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3929 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3931 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3933 vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3934 double angle=acos(vec[2]/normm);
3935 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3939 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3940 double normm2(sqrt(vec2[0]*vec2[0]+vec2[1]*vec2[1]+vec2[2]*vec2[2]));
3941 if(normm2/normm>1e-6)
3942 MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3943 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3945 mw->getBoundingBox(bbox);
3946 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3947 cellIds=mw->getCellsInBoundingBox(bbox,eps);
3951 getBoundingBox(bbox);
3952 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3953 cellIds=getCellsInBoundingBox(bbox,eps);
3955 return cellIds.retn();
3959 * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3960 * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3961 * No consideration of coordinate is done by this method.
3962 * 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)
3963 * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3965 bool MEDCouplingUMesh::isContiguous1D() const
3967 if(getMeshDimension()!=1)
3968 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3969 int nbCells=getNumberOfCells();
3971 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3972 const int *connI=_nodal_connec_index->getConstPointer();
3973 const int *conn=_nodal_connec->getConstPointer();
3974 int ref=conn[connI[0]+2];
3975 for(int i=1;i<nbCells;i++)
3977 if(conn[connI[i]+1]!=ref)
3979 ref=conn[connI[i]+2];
3985 * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3986 * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3987 * \param pt reference point of the line
3988 * \param v normalized director vector of the line
3989 * \param eps max precision before throwing an exception
3990 * \param res output of size this->getNumberOfCells
3992 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3994 if(getMeshDimension()!=1)
3995 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3996 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3997 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3998 if(getSpaceDimension()!=3)
3999 throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
4000 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
4001 const double *fPtr=f->getArray()->getConstPointer();
4003 for(int i=0;i<getNumberOfCells();i++)
4005 const double *tmp1=fPtr+3*i;
4006 tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
4007 tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
4008 tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
4009 double n1=INTERP_KERNEL::norm<3>(tmp);
4010 n1/=INTERP_KERNEL::norm<3>(tmp1);
4012 throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
4014 const double *coo=getCoords()->getConstPointer();
4015 for(int i=0;i<getNumberOfNodes();i++)
4017 std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
4018 std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
4019 res[i]=std::accumulate(tmp,tmp+3,0.);
4024 * 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.
4025 * \a this is expected to be a mesh so that its space dimension is equal to its
4026 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4027 * 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).
4029 * 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
4030 * 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).
4031 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4033 * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
4034 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4036 * \param [in] ptBg the start pointer (included) of the coordinates of the point
4037 * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
4038 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4039 * \return the positive value of the distance.
4040 * \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
4042 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
4044 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
4046 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4047 if(meshDim!=spaceDim-1)
4048 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
4049 if(meshDim!=2 && meshDim!=1)
4050 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4051 checkFullyDefined();
4052 if((int)std::distance(ptBg,ptEnd)!=spaceDim)
4053 { 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()); }
4054 DataArrayInt *ret1=0;
4055 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
4056 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
4057 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
4058 cellId=*ret1Safe->begin();
4059 return *ret0->begin();
4063 * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
4064 * to \a this and the first \a cellId in \a this corresponding to the returned distance.
4065 * 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
4066 * 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).
4067 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4069 * \a this is expected to be a mesh so that its space dimension is equal to its
4070 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4071 * 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).
4073 * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
4074 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4076 * \param [in] pts the list of points in which each tuple represents a point
4077 * \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.
4078 * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
4079 * \throw if number of components of \a pts is not equal to the space dimension.
4080 * \throw if mesh dimension of \a this is not equal to space dimension - 1.
4081 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
4083 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
4086 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
4087 pts->checkAllocated();
4088 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4089 if(meshDim!=spaceDim-1)
4090 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
4091 if(meshDim!=2 && meshDim!=1)
4092 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
4093 if(pts->getNumberOfComponents()!=spaceDim)
4095 std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
4096 throw INTERP_KERNEL::Exception(oss.str().c_str());
4098 checkFullyDefined();
4099 int nbCells=getNumberOfCells();
4101 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4102 int nbOfPts=pts->getNumberOfTuples();
4103 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4104 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4105 const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4106 double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4107 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4108 const double *bbox(bboxArr->begin());
4113 BBTreeDst<3> myTree(bbox,0,0,nbCells);
4114 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4116 double x=std::numeric_limits<double>::max();
4117 std::vector<int> elems;
4118 myTree.getMinDistanceOfMax(ptsPtr,x);
4119 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4120 DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4126 BBTreeDst<2> myTree(bbox,0,0,nbCells);
4127 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4129 double x=std::numeric_limits<double>::max();
4130 std::vector<int> elems;
4131 myTree.getMinDistanceOfMax(ptsPtr,x);
4132 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4133 DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4138 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4140 cellIds=ret1.retn();
4145 * \param [in] pt the start pointer (included) of the coordinates of the point
4146 * \param [in] cellIdsBg the start pointer (included) of cellIds
4147 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4148 * \param [in] nc nodal connectivity
4149 * \param [in] ncI nodal connectivity index
4150 * \param [in,out] ret0 the min distance between \a this and the external input point
4151 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4152 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4154 void MEDCouplingUMesh::DistanceToPoint3DSurfAlg(const double *pt, const int *cellIdsBg, const int *cellIdsEnd, const double *coords, const int *nc, const int *ncI, double& ret0, int& cellId)
4157 ret0=std::numeric_limits<double>::max();
4158 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4160 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4162 case INTERP_KERNEL::NORM_TRI3:
4164 double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4166 { ret0=tmp; cellId=*zeCell; }
4169 case INTERP_KERNEL::NORM_QUAD4:
4170 case INTERP_KERNEL::NORM_POLYGON:
4172 double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4174 { ret0=tmp; cellId=*zeCell; }
4178 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4184 * \param [in] pt the start pointer (included) of the coordinates of the point
4185 * \param [in] cellIdsBg the start pointer (included) of cellIds
4186 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4187 * \param [in] nc nodal connectivity
4188 * \param [in] ncI nodal connectivity index
4189 * \param [in,out] ret0 the min distance between \a this and the external input point
4190 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4191 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4193 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)
4196 ret0=std::numeric_limits<double>::max();
4197 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4199 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4201 case INTERP_KERNEL::NORM_SEG2:
4203 std::size_t uselessEntry=0;
4204 double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4207 { ret0=tmp; cellId=*zeCell; }
4211 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4217 * Finds cells in contact with a ball (i.e. a point with precision).
4218 * 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.
4219 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4221 * \warning This method is suitable if the caller intends to evaluate only one
4222 * point, for more points getCellsContainingPoints() is recommended as it is
4224 * \param [in] pos - array of coordinates of the ball central point.
4225 * \param [in] eps - ball radius.
4226 * \return int - a smallest id of cells being in contact with the ball, -1 in case
4227 * if there are no such cells.
4228 * \throw If the coordinates array is not set.
4229 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4231 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4233 std::vector<int> elts;
4234 getCellsContainingPoint(pos,eps,elts);
4237 return elts.front();
4241 * Finds cells in contact with a ball (i.e. a point with precision).
4242 * For speed reasons, the INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6 and INTERP_KERNEL::NORM_QUAD8 cells are considered as convex cells to detect if a point is IN or OUT.
4243 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4244 * \warning This method is suitable if the caller intends to evaluate only one
4245 * point, for more points getCellsContainingPoints() is recommended as it is
4247 * \param [in] pos - array of coordinates of the ball central point.
4248 * \param [in] eps - ball radius.
4249 * \param [out] elts - vector returning ids of the found cells. It is cleared
4250 * before inserting ids.
4251 * \throw If the coordinates array is not set.
4252 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4254 * \if ENABLE_EXAMPLES
4255 * \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4256 * \ref py_mcumesh_getCellsContainingPoint "Here is a Python example".
4259 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4261 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4262 getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4263 elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4268 namespace ParaMEDMEM
4270 template<const int SPACEDIMM>
4274 static const int MY_SPACEDIM=SPACEDIMM;
4275 static const int MY_MESHDIM=8;
4276 typedef int MyConnType;
4277 static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4279 // useless, but for windows compilation ...
4280 const double* getCoordinatesPtr() const { return 0; }
4281 const int* getConnectivityPtr() const { return 0; }
4282 const int* getConnectivityIndexPtr() const { return 0; }
4283 INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4287 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m)
4289 INTERP_KERNEL::Edge *ret(0);
4290 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]));
4291 m[n0]=bg[0]; m[n1]=bg[1];
4294 case INTERP_KERNEL::NORM_SEG2:
4296 ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4299 case INTERP_KERNEL::NORM_SEG3:
4301 INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4302 INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4303 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4304 // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4305 bool colinearity(inters.areColinears());
4306 delete e1; delete e2;
4308 { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4310 { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4314 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4319 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4321 INTERP_KERNEL::Edge *ret=0;
4324 case INTERP_KERNEL::NORM_SEG2:
4326 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4329 case INTERP_KERNEL::NORM_SEG3:
4331 INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4332 INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4333 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4334 // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4335 bool colinearity=inters.areColinears();
4336 delete e1; delete e2;
4338 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4340 ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4341 mapp2[bg[2]].second=false;
4345 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4351 * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4352 * the global mesh 'mDesc'.
4353 * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4354 * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4356 INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4357 std::map<INTERP_KERNEL::Node *,int>& mapp)
4360 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.
4361 const double *coo=mDesc->getCoords()->getConstPointer();
4362 const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4363 const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4365 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4366 s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4367 for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4369 INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4370 mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4372 INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4373 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4375 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4376 ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4378 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4380 if((*it2).second.second)
4381 mapp[(*it2).second.first]=(*it2).first;
4382 ((*it2).second.first)->decrRef();
4387 INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4391 int locId=nodeId-offset2;
4392 return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4396 int locId=nodeId-offset1;
4397 return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4399 return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4403 * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4405 void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4406 const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4407 /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4409 for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4411 int eltId1=abs(*desc1)-1;
4412 for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4414 std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4415 if(it==mappRev.end())
4417 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4428 template<int SPACEDIM>
4429 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4430 double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4432 elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4433 int *eltsIndexPtr(eltsIndex->getPointer());
4434 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4435 const double *bbox(bboxArr->begin());
4436 int nbOfCells=getNumberOfCells();
4437 const int *conn=_nodal_connec->getConstPointer();
4438 const int *connI=_nodal_connec_index->getConstPointer();
4439 double bb[2*SPACEDIM];
4440 BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4441 for(int i=0;i<nbOfPoints;i++)
4443 eltsIndexPtr[i+1]=eltsIndexPtr[i];
4444 for(int j=0;j<SPACEDIM;j++)
4446 bb[2*j]=pos[SPACEDIM*i+j];
4447 bb[2*j+1]=pos[SPACEDIM*i+j];
4449 std::vector<int> candidates;
4450 myTree.getIntersectingElems(bb,candidates);
4451 for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4453 int sz(connI[(*iter)+1]-connI[*iter]-1);
4454 INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4456 if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4457 status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4461 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4462 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4463 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4464 std::vector<INTERP_KERNEL::Node *> nodes(sz);
4465 INTERP_KERNEL::QuadraticPolygon *pol(0);
4466 for(int j=0;j<sz;j++)
4468 int nodeId(conn[connI[*iter]+1+j]);
4469 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4471 if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4472 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4474 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4475 INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4476 double a(0.),b(0.),c(0.);
4477 a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4478 status=pol->isInOrOut2(n);
4479 delete pol; n->decrRef();
4483 eltsIndexPtr[i+1]++;
4484 elts->pushBackSilent(*iter);
4490 * Finds cells in contact with several balls (i.e. points with precision).
4491 * This method is an extension of getCellContainingPoint() and
4492 * getCellsContainingPoint() for the case of multiple points.
4493 * 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.
4494 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4495 * \param [in] pos - an array of coordinates of points in full interlace mode :
4496 * X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4497 * this->getSpaceDimension() * \a nbOfPoints
4498 * \param [in] nbOfPoints - number of points to locate within \a this mesh.
4499 * \param [in] eps - radius of balls (i.e. the precision).
4500 * \param [out] elts - vector returning ids of found cells.
4501 * \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4502 * dividing cell ids in \a elts into groups each referring to one
4503 * point. Its every element (except the last one) is an index pointing to the
4504 * first id of a group of cells. For example cells in contact with the *i*-th
4505 * point are described by following range of indices:
4506 * [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4507 * \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4508 * Number of cells in contact with the *i*-th point is
4509 * \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4510 * \throw If the coordinates array is not set.
4511 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4513 * \if ENABLE_EXAMPLES
4514 * \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4515 * \ref py_mcumesh_getCellsContainingPoints "Here is a Python example".
4518 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4519 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4521 int spaceDim=getSpaceDimension();
4522 int mDim=getMeshDimension();
4527 const double *coords=_coords->getConstPointer();
4528 getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4535 throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4537 else if(spaceDim==2)
4541 const double *coords=_coords->getConstPointer();
4542 getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4545 throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4547 else if(spaceDim==1)
4551 const double *coords=_coords->getConstPointer();
4552 getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4555 throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4558 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4562 * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4563 * least two its edges intersect each other anywhere except their extremities. An
4564 * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4565 * \param [in,out] cells - a vector returning ids of the found cells. It is not
4566 * cleared before filling in.
4567 * \param [in] eps - precision.
4568 * \throw If \a this->getMeshDimension() != 2.
4569 * \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4571 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4573 const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4574 if(getMeshDimension()!=2)
4575 throw INTERP_KERNEL::Exception(msg);
4576 int spaceDim=getSpaceDimension();
4577 if(spaceDim!=2 && spaceDim!=3)
4578 throw INTERP_KERNEL::Exception(msg);
4579 const int *conn=_nodal_connec->getConstPointer();
4580 const int *connI=_nodal_connec_index->getConstPointer();
4581 int nbOfCells=getNumberOfCells();
4582 std::vector<double> cell2DinS2;
4583 for(int i=0;i<nbOfCells;i++)
4585 int offset=connI[i];
4586 int nbOfNodesForCell=connI[i+1]-offset-1;
4587 if(nbOfNodesForCell<=3)
4589 bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4590 project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4591 if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4598 * This method is typically requested to unbutterfly 2D linear cells in \b this.
4600 * 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.
4601 * 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.
4603 * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4604 * This convex envelop is computed using Jarvis march algorithm.
4605 * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4606 * 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)
4607 * 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.
4609 * \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.
4610 * \sa MEDCouplingUMesh::colinearize2D
4612 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4614 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4615 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D works only for meshDim=2 and spaceDim=2 !");
4616 checkFullyDefined();
4617 const double *coords=getCoords()->getConstPointer();
4618 int nbOfCells=getNumberOfCells();
4619 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4620 nodalConnecIndexOut->alloc(nbOfCells+1,1);
4621 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4622 int *workIndexOut=nodalConnecIndexOut->getPointer();
4624 const int *nodalConnecIn=_nodal_connec->getConstPointer();
4625 const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4626 std::set<INTERP_KERNEL::NormalizedCellType> types;
4627 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4628 isChanged->alloc(0,1);
4629 for(int i=0;i<nbOfCells;i++,workIndexOut++)
4631 int pos=nodalConnecOut->getNumberOfTuples();
4632 if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4633 isChanged->pushBackSilent(i);
4634 types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4635 workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4637 if(isChanged->empty())
4639 setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4641 return isChanged.retn();
4645 * This method is \b NOT const because it can modify \a this.
4646 * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4647 * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4648 * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4649 * \b 1 for translation and rotation around point of 'mesh1D'.
4650 * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.
4652 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4654 checkFullyDefined();
4655 mesh1D->checkFullyDefined();
4656 if(!mesh1D->isContiguous1D())
4657 throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4658 if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4659 throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4660 if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4661 throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4662 if(mesh1D->getMeshDimension()!=1)
4663 throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4665 if(isPresenceOfQuadratic())
4667 if(mesh1D->isFullyQuadratic())
4670 throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4672 int oldNbOfNodes(getNumberOfNodes());
4673 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4678 newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4683 newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4687 throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4689 setCoords(newCoords);
4690 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad));
4696 * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4697 * If it is not the case an exception will be thrown.
4698 * This method is non const because the coordinate of \a this can be appended with some new points issued from
4699 * intersection of plane defined by ('origin','vec').
4700 * This method has one in/out parameter : 'cut3DCurve'.
4701 * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4702 * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4703 * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4704 * This method will throw an exception if \a this contains a non linear segment.
4706 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4708 checkFullyDefined();
4709 if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4710 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4711 int ncells=getNumberOfCells();
4712 int nnodes=getNumberOfNodes();
4713 double vec2[3],vec3[3],vec4[3];
4714 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4716 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4717 vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4718 const int *conn=_nodal_connec->getConstPointer();
4719 const int *connI=_nodal_connec_index->getConstPointer();
4720 const double *coo=_coords->getConstPointer();
4721 std::vector<double> addCoo;
4722 for(int i=0;i<ncells;i++)
4724 if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4726 if(cut3DCurve[i]==-2)
4728 int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4729 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];
4730 double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4731 double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4732 if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4734 const double *st2=coo+3*st;
4735 vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4736 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]));
4737 if(pos>eps && pos<1-eps)
4739 int nNode=((int)addCoo.size())/3;
4740 vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4741 addCoo.insert(addCoo.end(),vec4,vec4+3);
4742 cut3DCurve[i]=nnodes+nNode;
4748 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4752 int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4753 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4754 coo2->alloc(newNbOfNodes,3);
4755 double *tmp=coo2->getPointer();
4756 tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4757 std::copy(addCoo.begin(),addCoo.end(),tmp);
4758 DataArrayDouble::SetArrayIn(coo2,_coords);
4763 * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4764 * \param mesh1D is the input 1D mesh used for translation computation.
4765 * \return newCoords new coords filled by this method.
4767 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4769 int oldNbOfNodes=getNumberOfNodes();
4770 int nbOf1DCells=mesh1D->getNumberOfCells();
4771 int spaceDim=getSpaceDimension();
4772 DataArrayDouble *ret=DataArrayDouble::New();
4773 std::vector<bool> isQuads;
4774 int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4775 ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4776 double *retPtr=ret->getPointer();
4777 const double *coords=getCoords()->getConstPointer();
4778 double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4780 std::vector<double> c;
4784 for(int i=0;i<nbOf1DCells;i++)
4787 mesh1D->getNodeIdsOfCell(i,v);
4789 mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4790 mesh1D->getCoordinatesOfNode(v[0],c);
4791 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4792 for(int j=0;j<oldNbOfNodes;j++)
4793 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4797 mesh1D->getCoordinatesOfNode(v[1],c);
4798 mesh1D->getCoordinatesOfNode(v[0],c);
4799 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4800 for(int j=0;j<oldNbOfNodes;j++)
4801 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4804 ret->copyStringInfoFrom(*getCoords());
4809 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4810 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4811 * \return newCoords new coords filled by this method.
4813 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4815 if(mesh1D->getSpaceDimension()==2)
4816 return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4817 if(mesh1D->getSpaceDimension()==3)
4818 return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4819 throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4823 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4824 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4825 * \return newCoords new coords filled by this method.
4827 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4830 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4831 int oldNbOfNodes=getNumberOfNodes();
4832 int nbOf1DCells=mesh1D->getNumberOfCells();
4834 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4835 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4836 int nbOfLevsInVec=nbOf1DCells+1;
4837 ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4838 double *retPtr=ret->getPointer();
4839 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4840 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4841 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4842 tmp->setCoords(tmp2);
4843 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4844 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4845 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4846 for(int i=1;i<nbOfLevsInVec;i++)
4848 const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4849 const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4850 const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4851 const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4852 tmp->translate(vec);
4853 double tmp3[2],radius,alpha,alpha0;
4854 const double *p0=i+1<nbOfLevsInVec?begin:third;
4855 const double *p1=i+1<nbOfLevsInVec?end:begin;
4856 const double *p2=i+1<nbOfLevsInVec?third:end;
4857 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4858 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]);
4859 double angle=acos(cosangle/(radius*radius));
4860 tmp->rotate(end,0,angle);
4861 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4867 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4868 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4869 * \return newCoords new coords filled by this method.
4871 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4874 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4875 int oldNbOfNodes=getNumberOfNodes();
4876 int nbOf1DCells=mesh1D->getNumberOfCells();
4878 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4879 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4880 int nbOfLevsInVec=nbOf1DCells+1;
4881 ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4882 double *retPtr=ret->getPointer();
4883 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4884 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4885 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4886 tmp->setCoords(tmp2);
4887 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4888 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4889 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4890 for(int i=1;i<nbOfLevsInVec;i++)
4892 const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4893 const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4894 const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4895 const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4896 tmp->translate(vec);
4897 double tmp3[2],radius,alpha,alpha0;
4898 const double *p0=i+1<nbOfLevsInVec?begin:third;
4899 const double *p1=i+1<nbOfLevsInVec?end:begin;
4900 const double *p2=i+1<nbOfLevsInVec?third:end;
4901 double vecPlane[3]={
4902 (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4903 (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4904 (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4906 double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4909 vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4910 double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4911 double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4913 double c2=cos(asin(s2));
4915 {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4916 {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4917 {-vec2[1]*s2, vec2[0]*s2, c2}
4919 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]};
4920 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]};
4921 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]};
4922 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4923 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]);
4924 double angle=acos(cosangle/(radius*radius));
4925 tmp->rotate(end,vecPlane,angle);
4927 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4933 * This method is private because not easy to use for end user. This method is const contrary to
4934 * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4935 * the coords sorted slice by slice.
4936 * \param isQuad specifies presence of quadratic cells.
4938 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4940 int nbOf1DCells(getNumberOfNodes()/nbOfNodesOf1Lev-1);
4941 int nbOf2DCells(getNumberOfCells());
4942 int nbOf3DCells(nbOf2DCells*nbOf1DCells);
4943 MEDCouplingUMesh *ret(MEDCouplingUMesh::New("Extruded",getMeshDimension()+1));
4944 const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
4945 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()),newConnI(DataArrayInt::New());
4946 newConnI->alloc(nbOf3DCells+1,1);
4947 int *newConnIPtr(newConnI->getPointer());
4949 std::vector<int> newc;
4950 for(int j=0;j<nbOf2DCells;j++)
4952 AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4953 *newConnIPtr++=(int)newc.size();
4955 newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4956 int *newConnPtr(newConn->getPointer());
4957 int deltaPerLev(isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev);
4958 newConnIPtr=newConnI->getPointer();
4959 for(int iz=0;iz<nbOf1DCells;iz++)
4962 std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4963 const int *posOfTypeOfCell(newConnIPtr);
4964 for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4966 int icell((int)(iter-newc.begin()));//std::distance unfortunately cannot been called here in C++98
4967 if(icell!=*posOfTypeOfCell)
4970 *newConnPtr=(*iter)+iz*deltaPerLev;
4981 ret->setConnectivity(newConn,newConnI,true);
4982 ret->setCoords(getCoords());
4987 * Checks if \a this mesh is constituted by only quadratic cells.
4988 * \return bool - \c true if there are only quadratic cells in \a this mesh.
4989 * \throw If the coordinates array is not set.
4990 * \throw If the nodal connectivity of cells is not defined.
4992 bool MEDCouplingUMesh::isFullyQuadratic() const
4994 checkFullyDefined();
4996 int nbOfCells=getNumberOfCells();
4997 for(int i=0;i<nbOfCells && ret;i++)
4999 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5000 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5001 ret=cm.isQuadratic();
5007 * Checks if \a this mesh includes any quadratic cell.
5008 * \return bool - \c true if there is at least one quadratic cells in \a this mesh.
5009 * \throw If the coordinates array is not set.
5010 * \throw If the nodal connectivity of cells is not defined.
5012 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
5014 checkFullyDefined();
5016 int nbOfCells=getNumberOfCells();
5017 for(int i=0;i<nbOfCells && !ret;i++)
5019 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5020 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5021 ret=cm.isQuadratic();
5027 * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
5028 * this mesh, it remains unchanged.
5029 * \throw If the coordinates array is not set.
5030 * \throw If the nodal connectivity of cells is not defined.
5032 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
5034 checkFullyDefined();
5035 int nbOfCells=getNumberOfCells();
5037 const int *iciptr=_nodal_connec_index->getConstPointer();
5038 for(int i=0;i<nbOfCells;i++)
5040 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5041 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5042 if(cm.isQuadratic())
5044 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5045 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5046 if(!cml.isDynamic())
5047 delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
5049 delta+=(iciptr[i+1]-iciptr[i]-1)/2;
5054 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5055 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5056 const int *icptr=_nodal_connec->getConstPointer();
5057 newConn->alloc(getMeshLength()-delta,1);
5058 newConnI->alloc(nbOfCells+1,1);
5059 int *ocptr=newConn->getPointer();
5060 int *ociptr=newConnI->getPointer();
5063 for(int i=0;i<nbOfCells;i++,ociptr++)
5065 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
5066 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5067 if(!cm.isQuadratic())
5069 _types.insert(type);
5070 ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5071 ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5075 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5076 _types.insert(typel);
5077 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5078 int newNbOfNodes=cml.getNumberOfNodes();
5080 newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
5081 *ocptr++=(int)typel;
5082 ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5083 ociptr[1]=ociptr[0]+newNbOfNodes+1;
5086 setConnectivity(newConn,newConnI,false);
5090 * This method converts all linear cell in \a this to quadratic one.
5091 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5092 * 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)
5093 * 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.
5094 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5095 * end of the existing coordinates.
5097 * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5098 * corresponding quadratic cells. 1 is those creating the 'most' complex.
5099 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5101 * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5103 * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5105 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5107 DataArrayInt *conn=0,*connI=0;
5108 DataArrayDouble *coords=0;
5109 std::set<INTERP_KERNEL::NormalizedCellType> types;
5110 checkFullyDefined();
5111 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5112 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5113 int meshDim=getMeshDimension();
5114 switch(conversionType)
5120 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5121 connSafe=conn; connISafe=connI; coordsSafe=coords;
5124 ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5125 connSafe=conn; connISafe=connI; coordsSafe=coords;
5128 ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5129 connSafe=conn; connISafe=connI; coordsSafe=coords;
5132 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5140 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5141 connSafe=conn; connISafe=connI; coordsSafe=coords;
5144 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5145 connSafe=conn; connISafe=connI; coordsSafe=coords;
5148 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5149 connSafe=conn; connISafe=connI; coordsSafe=coords;
5152 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5157 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5159 setConnectivity(connSafe,connISafe,false);
5161 setCoords(coordsSafe);
5167 * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
5168 * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
5169 * The nodes to be added in those 2D cells are defined by the pair of \a nodeIdsToAdd and \a nodeIdsIndexToAdd.
5170 * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
5171 * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
5172 * This method can be seen as the opposite method of colinearize2D.
5173 * 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
5174 * to avoid to modify the numbering of existing nodes.
5176 * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
5177 * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
5178 * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
5179 * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
5180 * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
5181 * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
5182 * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
5184 * \sa buildDescendingConnectivity2
5186 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
5187 const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
5189 if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
5190 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
5191 nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
5192 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
5193 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
5194 if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
5195 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
5196 //DataArrayInt *out0(0),*outi0(0);
5197 //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
5198 //MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s(out0),outi0s(outi0);
5199 //out0s=out0s->buildUnique(); out0s->sort(true);
5204 * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5205 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5206 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5208 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5210 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5211 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5212 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5213 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5214 int nbOfCells=getNumberOfCells();
5215 int nbOfNodes=getNumberOfNodes();
5216 const int *cPtr=_nodal_connec->getConstPointer();
5217 const int *icPtr=_nodal_connec_index->getConstPointer();
5218 int lastVal=0,offset=nbOfNodes;
5219 for(int i=0;i<nbOfCells;i++,icPtr++)
5221 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5222 if(type==INTERP_KERNEL::NORM_SEG2)
5224 types.insert(INTERP_KERNEL::NORM_SEG3);
5225 newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5226 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5227 newConn->pushBackSilent(offset++);
5229 newConnI->pushBackSilent(lastVal);
5230 ret->pushBackSilent(i);
5235 lastVal+=(icPtr[1]-icPtr[0]);
5236 newConnI->pushBackSilent(lastVal);
5237 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5240 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5241 coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5245 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
5247 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5248 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5249 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5251 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5252 DataArrayInt *conn1D=0,*conn1DI=0;
5253 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5254 DataArrayDouble *coordsTmp=0;
5255 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5256 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5257 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5258 const int *c1DPtr=conn1D->begin();
5259 const int *c1DIPtr=conn1DI->begin();
5260 int nbOfCells=getNumberOfCells();
5261 const int *cPtr=_nodal_connec->getConstPointer();
5262 const int *icPtr=_nodal_connec_index->getConstPointer();
5264 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5266 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5267 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5268 if(!cm.isQuadratic())
5270 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5271 types.insert(typ2); newConn->pushBackSilent(typ2);
5272 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5273 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5274 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5275 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5276 newConnI->pushBackSilent(lastVal);
5277 ret->pushBackSilent(i);
5282 lastVal+=(icPtr[1]-icPtr[0]);
5283 newConnI->pushBackSilent(lastVal);
5284 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5287 conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5292 * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5293 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5294 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5296 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5298 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5299 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5300 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5303 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5305 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5306 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5308 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5309 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5310 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5312 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5313 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5314 DataArrayInt *conn1D=0,*conn1DI=0;
5315 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5316 DataArrayDouble *coordsTmp=0;
5317 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5318 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5319 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5320 const int *c1DPtr=conn1D->begin();
5321 const int *c1DIPtr=conn1DI->begin();
5322 int nbOfCells=getNumberOfCells();
5323 const int *cPtr=_nodal_connec->getConstPointer();
5324 const int *icPtr=_nodal_connec_index->getConstPointer();
5325 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5326 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5328 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5329 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5330 if(!cm.isQuadratic())
5332 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5333 types.insert(typ2); newConn->pushBackSilent(typ2);
5334 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5335 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5336 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5337 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5338 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5339 newConnI->pushBackSilent(lastVal);
5340 ret->pushBackSilent(i);
5345 lastVal+=(icPtr[1]-icPtr[0]);
5346 newConnI->pushBackSilent(lastVal);
5347 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5350 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5351 coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5356 * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5357 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5358 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5360 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5362 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5363 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5364 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5367 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5369 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5370 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5371 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5372 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5374 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5375 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5376 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5378 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5379 const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5380 DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5381 std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5382 DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5383 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5384 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5385 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5386 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5387 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5388 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5389 const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5390 int nbOfCells=getNumberOfCells();
5391 const int *cPtr=_nodal_connec->getConstPointer();
5392 const int *icPtr=_nodal_connec_index->getConstPointer();
5393 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5394 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5396 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5397 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5398 if(!cm.isQuadratic())
5400 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5401 if(typ2==INTERP_KERNEL::NORM_ERROR)
5403 std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5404 throw INTERP_KERNEL::Exception(oss.str().c_str());
5406 types.insert(typ2); newConn->pushBackSilent(typ2);
5407 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5408 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5409 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5410 for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5412 int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5413 int tmpPos=newConn->getNumberOfTuples();
5414 newConn->pushBackSilent(nodeId2);
5415 ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5417 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5418 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5419 newConnI->pushBackSilent(lastVal);
5420 ret->pushBackSilent(i);
5425 lastVal+=(icPtr[1]-icPtr[0]);
5426 newConnI->pushBackSilent(lastVal);
5427 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5430 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5431 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5432 coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5433 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5434 std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5435 int *c=newConn->getPointer();
5436 const int *cI(newConnI->begin());
5437 for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5438 c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5439 offset=coordsTmp2Safe->getNumberOfTuples();
5440 for(const int *elt=ret->begin();elt!=ret->end();elt++)
5441 c[cI[(*elt)+1]-1]+=offset;
5442 coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5447 * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5448 * so that the number of cells remains the same. Quadratic faces are converted to
5449 * polygons. This method works only for 2D meshes in
5450 * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5451 * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5452 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5453 * \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5454 * a polylinized edge constituting the input polygon.
5455 * \throw If the coordinates array is not set.
5456 * \throw If the nodal connectivity of cells is not defined.
5457 * \throw If \a this->getMeshDimension() != 2.
5458 * \throw If \a this->getSpaceDimension() != 2.
5460 void MEDCouplingUMesh::tessellate2D(double eps)
5462 checkFullyDefined();
5463 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
5464 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5465 double epsa=fabs(eps);
5466 if(epsa<std::numeric_limits<double>::min())
5467 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 !");
5468 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5469 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5470 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5471 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5472 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5473 revDesc1=0; revDescIndx1=0;
5474 mDesc->tessellate2DCurve(eps);
5475 subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5476 setCoords(mDesc->getCoords());
5480 * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5481 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5482 * \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5483 * a sub-divided edge.
5484 * \throw If the coordinates array is not set.
5485 * \throw If the nodal connectivity of cells is not defined.
5486 * \throw If \a this->getMeshDimension() != 1.
5487 * \throw If \a this->getSpaceDimension() != 2.
5489 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5491 checkFullyDefined();
5492 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5493 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5494 double epsa=fabs(eps);
5495 if(epsa<std::numeric_limits<double>::min())
5496 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve : epsilon is null ! Please specify a higher epsilon. If too tiny it can lead to a huge amount of nodes and memory !");
5497 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5498 int nbCells=getNumberOfCells();
5499 int nbNodes=getNumberOfNodes();
5500 const int *conn=_nodal_connec->getConstPointer();
5501 const int *connI=_nodal_connec_index->getConstPointer();
5502 const double *coords=_coords->getConstPointer();
5503 std::vector<double> addCoo;
5504 std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5505 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5506 newConnI->alloc(nbCells+1,1);
5507 int *newConnIPtr=newConnI->getPointer();
5510 INTERP_KERNEL::Node *tmp2[3];
5511 std::set<INTERP_KERNEL::NormalizedCellType> types;
5512 for(int i=0;i<nbCells;i++,newConnIPtr++)
5514 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5515 if(cm.isQuadratic())
5516 {//assert(connI[i+1]-connI[i]-1==3)
5517 tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5518 tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5519 tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5520 tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5521 INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5524 eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5525 types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5527 newConnIPtr[1]=(int)newConn.size();
5531 types.insert(INTERP_KERNEL::NORM_SEG2);
5532 newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5533 newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5534 newConnIPtr[1]=newConnIPtr[0]+3;
5539 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5540 newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5541 newConnIPtr[1]=newConnIPtr[0]+3;
5544 if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5547 DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5548 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5549 newConnArr->alloc((int)newConn.size(),1);
5550 std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5551 DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5552 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5553 newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5554 double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5555 std::copy(addCoo.begin(),addCoo.end(),work);
5556 DataArrayDouble::SetArrayIn(newCoords,_coords);
5561 * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5562 * In addition, returns an array mapping new cells to old ones. <br>
5563 * This method typically increases the number of cells in \a this mesh
5564 * but the number of nodes remains \b unchanged.
5565 * That's why the 3D splitting policies
5566 * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5567 * \param [in] policy - specifies a pattern used for splitting.
5568 * The semantic of \a policy is:
5569 * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5570 * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5571 * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8 into 5 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5572 * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8 into 6 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5575 * \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5576 * an id of old cell producing it. The caller is to delete this array using
5577 * decrRef() as it is no more needed.
5579 * \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5580 * \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5581 * and \a this->getMeshDimension() != 3.
5582 * \throw If \a policy is not one of the four discussed above.
5583 * \throw If the nodal connectivity of cells is not defined.
5584 * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5586 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5591 return simplexizePol0();
5593 return simplexizePol1();
5594 case (int) INTERP_KERNEL::PLANAR_FACE_5:
5595 return simplexizePlanarFace5();
5596 case (int) INTERP_KERNEL::PLANAR_FACE_6:
5597 return simplexizePlanarFace6();
5599 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)");
5604 * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5605 * - 1D: INTERP_KERNEL::NORM_SEG2
5606 * - 2D: INTERP_KERNEL::NORM_TRI3
5607 * - 3D: INTERP_KERNEL::NORM_TETRA4.
5609 * This method is useful for users that need to use P1 field services as
5610 * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5611 * All these methods need mesh support containing only simplex cells.
5612 * \return bool - \c true if there are only simplex cells in \a this mesh.
5613 * \throw If the coordinates array is not set.
5614 * \throw If the nodal connectivity of cells is not defined.
5615 * \throw If \a this->getMeshDimension() < 1.
5617 bool MEDCouplingUMesh::areOnlySimplexCells() const
5619 checkFullyDefined();
5620 int mdim=getMeshDimension();
5621 if(mdim<1 || mdim>3)
5622 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5623 int nbCells=getNumberOfCells();
5624 const int *conn=_nodal_connec->getConstPointer();
5625 const int *connI=_nodal_connec_index->getConstPointer();
5626 for(int i=0;i<nbCells;i++)
5628 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5636 * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5638 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5640 checkConnectivityFullyDefined();
5641 if(getMeshDimension()!=2)
5642 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5643 int nbOfCells=getNumberOfCells();
5644 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5645 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5646 ret->alloc(nbOfCells+nbOfCutCells,1);
5647 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5648 int *retPt=ret->getPointer();
5649 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5650 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5651 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5652 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5653 int *pt=newConn->getPointer();
5654 int *ptI=newConnI->getPointer();
5656 const int *oldc=_nodal_connec->getConstPointer();
5657 const int *ci=_nodal_connec_index->getConstPointer();
5658 for(int i=0;i<nbOfCells;i++,ci++)
5660 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5662 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5663 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5664 pt=std::copy(tmp,tmp+8,pt);
5673 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5674 ptI[1]=ptI[0]+ci[1]-ci[0];
5679 _nodal_connec->decrRef();
5680 _nodal_connec=newConn.retn();
5681 _nodal_connec_index->decrRef();
5682 _nodal_connec_index=newConnI.retn();
5689 * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5691 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5693 checkConnectivityFullyDefined();
5694 if(getMeshDimension()!=2)
5695 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5696 int nbOfCells=getNumberOfCells();
5697 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5698 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5699 ret->alloc(nbOfCells+nbOfCutCells,1);
5700 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5701 int *retPt=ret->getPointer();
5702 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5703 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5704 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5705 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5706 int *pt=newConn->getPointer();
5707 int *ptI=newConnI->getPointer();
5709 const int *oldc=_nodal_connec->getConstPointer();
5710 const int *ci=_nodal_connec_index->getConstPointer();
5711 for(int i=0;i<nbOfCells;i++,ci++)
5713 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5715 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5716 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5717 pt=std::copy(tmp,tmp+8,pt);
5726 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5727 ptI[1]=ptI[0]+ci[1]-ci[0];
5732 _nodal_connec->decrRef();
5733 _nodal_connec=newConn.retn();
5734 _nodal_connec_index->decrRef();
5735 _nodal_connec_index=newConnI.retn();
5742 * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5744 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5746 checkConnectivityFullyDefined();
5747 if(getMeshDimension()!=3)
5748 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5749 int nbOfCells=getNumberOfCells();
5750 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5751 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5752 ret->alloc(nbOfCells+4*nbOfCutCells,1);
5753 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5754 int *retPt=ret->getPointer();
5755 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5756 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5757 newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5758 newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5759 int *pt=newConn->getPointer();
5760 int *ptI=newConnI->getPointer();
5762 const int *oldc=_nodal_connec->getConstPointer();
5763 const int *ci=_nodal_connec_index->getConstPointer();
5764 for(int i=0;i<nbOfCells;i++,ci++)
5766 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5768 for(int j=0;j<5;j++,pt+=5,ptI++)
5770 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5771 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];
5778 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5779 ptI[1]=ptI[0]+ci[1]-ci[0];
5784 _nodal_connec->decrRef();
5785 _nodal_connec=newConn.retn();
5786 _nodal_connec_index->decrRef();
5787 _nodal_connec_index=newConnI.retn();
5794 * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5796 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5798 checkConnectivityFullyDefined();
5799 if(getMeshDimension()!=3)
5800 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5801 int nbOfCells=getNumberOfCells();
5802 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5803 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5804 ret->alloc(nbOfCells+5*nbOfCutCells,1);
5805 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5806 int *retPt=ret->getPointer();
5807 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5808 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5809 newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5810 newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5811 int *pt=newConn->getPointer();
5812 int *ptI=newConnI->getPointer();
5814 const int *oldc=_nodal_connec->getConstPointer();
5815 const int *ci=_nodal_connec_index->getConstPointer();
5816 for(int i=0;i<nbOfCells;i++,ci++)
5818 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5820 for(int j=0;j<6;j++,pt+=5,ptI++)
5822 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5823 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];
5830 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5831 ptI[1]=ptI[0]+ci[1]-ci[0];
5836 _nodal_connec->decrRef();
5837 _nodal_connec=newConn.retn();
5838 _nodal_connec_index->decrRef();
5839 _nodal_connec_index=newConnI.retn();
5846 * 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.
5847 * This method completly ignore coordinates.
5848 * \param nodeSubdived is the nodal connectivity of subdivision of edges
5849 * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5850 * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5851 * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5853 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5855 checkFullyDefined();
5856 if(getMeshDimension()!=2)
5857 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5858 int nbOfCells=getNumberOfCells();
5859 int *connI=_nodal_connec_index->getPointer();
5861 for(int i=0;i<nbOfCells;i++,connI++)
5863 int offset=descIndex[i];
5864 int nbOfEdges=descIndex[i+1]-offset;
5866 bool ddirect=desc[offset+nbOfEdges-1]>0;
5867 int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5868 int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5869 for(int j=0;j<nbOfEdges;j++)
5871 bool direct=desc[offset+j]>0;
5872 int edgeId=std::abs(desc[offset+j])-1;
5873 if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5875 int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5876 int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5877 int ref2=direct?id1:id2;
5880 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5881 newConnLgth+=nbOfSubNodes-1;
5886 std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5887 throw INTERP_KERNEL::Exception(oss.str().c_str());
5892 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5895 newConnLgth++;//+1 is for cell type
5896 connI[1]=newConnLgth;
5899 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5900 newConn->alloc(newConnLgth,1);
5901 int *work=newConn->getPointer();
5902 for(int i=0;i<nbOfCells;i++)
5904 *work++=INTERP_KERNEL::NORM_POLYGON;
5905 int offset=descIndex[i];
5906 int nbOfEdges=descIndex[i+1]-offset;
5907 for(int j=0;j<nbOfEdges;j++)
5909 bool direct=desc[offset+j]>0;
5910 int edgeId=std::abs(desc[offset+j])-1;
5912 work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5915 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5916 std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5917 work=std::copy(it,it+nbOfSubNodes-1,work);
5921 DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5924 _types.insert(INTERP_KERNEL::NORM_POLYGON);
5928 * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5929 * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5930 * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5931 * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5932 * so it can be useful to call mergeNodes() before calling this method.
5933 * \throw If \a this->getMeshDimension() <= 1.
5934 * \throw If the coordinates array is not set.
5935 * \throw If the nodal connectivity of cells is not defined.
5937 void MEDCouplingUMesh::convertDegeneratedCells()
5939 checkFullyDefined();
5940 if(getMeshDimension()<=1)
5941 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5942 int nbOfCells=getNumberOfCells();
5945 int initMeshLgth=getMeshLength();
5946 int *conn=_nodal_connec->getPointer();
5947 int *index=_nodal_connec_index->getPointer();
5951 for(int i=0;i<nbOfCells;i++)
5953 lgthOfCurCell=index[i+1]-posOfCurCell;
5954 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5956 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5957 conn+newPos+1,newLgth);
5958 conn[newPos]=newType;
5960 posOfCurCell=index[i+1];
5963 if(newPos!=initMeshLgth)
5964 _nodal_connec->reAlloc(newPos);
5969 * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5970 * A cell is considered to be oriented correctly if an angle between its
5971 * normal vector and a given vector is less than \c PI / \c 2.
5972 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5974 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5976 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5977 * is not cleared before filling in.
5978 * \throw If \a this->getMeshDimension() != 2.
5979 * \throw If \a this->getSpaceDimension() != 3.
5981 * \if ENABLE_EXAMPLES
5982 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5983 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5986 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
5988 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5989 throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5990 int nbOfCells=getNumberOfCells();
5991 const int *conn=_nodal_connec->getConstPointer();
5992 const int *connI=_nodal_connec_index->getConstPointer();
5993 const double *coordsPtr=_coords->getConstPointer();
5994 for(int i=0;i<nbOfCells;i++)
5996 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5997 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5999 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
6000 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6007 * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
6008 * considered to be oriented correctly if an angle between its normal vector and a
6009 * given vector is less than \c PI / \c 2.
6010 * \param [in] vec - 3 components of the vector specifying the correct orientation of
6012 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
6014 * \throw If \a this->getMeshDimension() != 2.
6015 * \throw If \a this->getSpaceDimension() != 3.
6017 * \if ENABLE_EXAMPLES
6018 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
6019 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
6022 * \sa changeOrientationOfCells
6024 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
6026 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6027 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
6028 int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6029 const int *connI(_nodal_connec_index->getConstPointer());
6030 const double *coordsPtr(_coords->getConstPointer());
6031 bool isModified(false);
6032 for(int i=0;i<nbOfCells;i++)
6034 INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6035 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6037 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6038 bool isQuadratic(cm.isQuadratic());
6039 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6042 cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6047 _nodal_connec->declareAsNew();
6052 * This method change the orientation of cells in \a this without any consideration of coordinates. Only connectivity is impacted.
6054 * \sa orientCorrectly2DCells
6056 void MEDCouplingUMesh::changeOrientationOfCells()
6058 int mdim(getMeshDimension());
6059 if(mdim!=2 && mdim!=1)
6060 throw INTERP_KERNEL::Exception("Invalid mesh to apply changeOrientationOfCells on it : must be meshDim==2 or meshDim==1 !");
6061 int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6062 const int *connI(_nodal_connec_index->getConstPointer());
6065 for(int i=0;i<nbOfCells;i++)
6067 INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6068 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6069 cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6074 for(int i=0;i<nbOfCells;i++)
6076 INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6077 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6078 cm.changeOrientationOf1D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6084 * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
6085 * oriented facets. The normal vector of the facet should point out of the cell.
6086 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6087 * is not cleared before filling in.
6088 * \throw If \a this->getMeshDimension() != 3.
6089 * \throw If \a this->getSpaceDimension() != 3.
6090 * \throw If the coordinates array is not set.
6091 * \throw If the nodal connectivity of cells is not defined.
6093 * \if ENABLE_EXAMPLES
6094 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6095 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6098 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
6100 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6101 throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
6102 int nbOfCells=getNumberOfCells();
6103 const int *conn=_nodal_connec->getConstPointer();
6104 const int *connI=_nodal_connec_index->getConstPointer();
6105 const double *coordsPtr=_coords->getConstPointer();
6106 for(int i=0;i<nbOfCells;i++)
6108 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6109 if(type==INTERP_KERNEL::NORM_POLYHED)
6111 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6118 * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6120 * \throw If \a this->getMeshDimension() != 3.
6121 * \throw If \a this->getSpaceDimension() != 3.
6122 * \throw If the coordinates array is not set.
6123 * \throw If the nodal connectivity of cells is not defined.
6124 * \throw If the reparation fails.
6126 * \if ENABLE_EXAMPLES
6127 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6128 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6130 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6132 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
6134 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6135 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6136 int nbOfCells=getNumberOfCells();
6137 int *conn=_nodal_connec->getPointer();
6138 const int *connI=_nodal_connec_index->getConstPointer();
6139 const double *coordsPtr=_coords->getConstPointer();
6140 for(int i=0;i<nbOfCells;i++)
6142 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6143 if(type==INTERP_KERNEL::NORM_POLYHED)
6147 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6148 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6150 catch(INTERP_KERNEL::Exception& e)
6152 std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6153 throw INTERP_KERNEL::Exception(oss.str().c_str());
6161 * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6162 * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6163 * according to which the first facet of the cell should be oriented to have the normal vector
6164 * pointing out of cell.
6165 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6166 * cells. The caller is to delete this array using decrRef() as it is no more
6168 * \throw If \a this->getMeshDimension() != 3.
6169 * \throw If \a this->getSpaceDimension() != 3.
6170 * \throw If the coordinates array is not set.
6171 * \throw If the nodal connectivity of cells is not defined.
6173 * \if ENABLE_EXAMPLES
6174 * \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6175 * \ref py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6177 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6179 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6181 const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6182 if(getMeshDimension()!=3)
6183 throw INTERP_KERNEL::Exception(msg);
6184 int spaceDim=getSpaceDimension();
6186 throw INTERP_KERNEL::Exception(msg);
6188 int nbOfCells=getNumberOfCells();
6189 int *conn=_nodal_connec->getPointer();
6190 const int *connI=_nodal_connec_index->getConstPointer();
6191 const double *coo=getCoords()->getConstPointer();
6192 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6193 for(int i=0;i<nbOfCells;i++)
6195 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6196 if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6198 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6200 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6201 cells->pushBackSilent(i);
6205 return cells.retn();
6209 * This method is a faster method to correct orientation of all 3D cells in \a this.
6210 * 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.
6211 * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6213 * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6214 * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons,
6216 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6218 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6219 throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6220 int nbOfCells=getNumberOfCells();
6221 int *conn=_nodal_connec->getPointer();
6222 const int *connI=_nodal_connec_index->getConstPointer();
6223 const double *coordsPtr=_coords->getConstPointer();
6224 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6225 for(int i=0;i<nbOfCells;i++)
6227 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6230 case INTERP_KERNEL::NORM_TETRA4:
6232 if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6234 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6235 ret->pushBackSilent(i);
6239 case INTERP_KERNEL::NORM_PYRA5:
6241 if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6243 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6244 ret->pushBackSilent(i);
6248 case INTERP_KERNEL::NORM_PENTA6:
6249 case INTERP_KERNEL::NORM_HEXA8:
6250 case INTERP_KERNEL::NORM_HEXGP12:
6252 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6254 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6255 ret->pushBackSilent(i);
6259 case INTERP_KERNEL::NORM_POLYHED:
6261 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6263 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6264 ret->pushBackSilent(i);
6269 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 !");
6277 * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6278 * If it is not the case an exception will be thrown.
6279 * This method is fast because the first cell of \a this is used to compute the plane.
6280 * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6281 * \param pos output of size at least 3 used to store a point owned of searched plane.
6283 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6285 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6286 throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6287 const int *conn=_nodal_connec->getConstPointer();
6288 const int *connI=_nodal_connec_index->getConstPointer();
6289 const double *coordsPtr=_coords->getConstPointer();
6290 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6291 std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6295 * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6296 * cells. Currently cells of the following types are treated:
6297 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6298 * For a cell of other type an exception is thrown.
6299 * Space dimension of a 2D mesh can be either 2 or 3.
6300 * The Edge Ratio of a cell \f$t\f$ is:
6301 * \f$\frac{|t|_\infty}{|t|_0}\f$,
6302 * where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6303 * the smallest edge lengths of \f$t\f$.
6304 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6305 * cells and one time, lying on \a this mesh. The caller is to delete this
6306 * field using decrRef() as it is no more needed.
6307 * \throw If the coordinates array is not set.
6308 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6309 * \throw If the connectivity data array has more than one component.
6310 * \throw If the connectivity data array has a named component.
6311 * \throw If the connectivity index data array has more than one component.
6312 * \throw If the connectivity index data array has a named component.
6313 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6314 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6315 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6317 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6320 int spaceDim=getSpaceDimension();
6321 int meshDim=getMeshDimension();
6322 if(spaceDim!=2 && spaceDim!=3)
6323 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6324 if(meshDim!=2 && meshDim!=3)
6325 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6326 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6328 int nbOfCells=getNumberOfCells();
6329 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6330 arr->alloc(nbOfCells,1);
6331 double *pt=arr->getPointer();
6332 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6333 const int *conn=_nodal_connec->getConstPointer();
6334 const int *connI=_nodal_connec_index->getConstPointer();
6335 const double *coo=_coords->getConstPointer();
6337 for(int i=0;i<nbOfCells;i++,pt++)
6339 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6342 case INTERP_KERNEL::NORM_TRI3:
6344 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6345 *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6348 case INTERP_KERNEL::NORM_QUAD4:
6350 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6351 *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6354 case INTERP_KERNEL::NORM_TETRA4:
6356 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6357 *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6361 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6363 conn+=connI[i+1]-connI[i];
6365 ret->setName("EdgeRatio");
6366 ret->synchronizeTimeWithSupport();
6371 * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6372 * cells. Currently cells of the following types are treated:
6373 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6374 * For a cell of other type an exception is thrown.
6375 * Space dimension of a 2D mesh can be either 2 or 3.
6376 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6377 * cells and one time, lying on \a this mesh. The caller is to delete this
6378 * field using decrRef() as it is no more needed.
6379 * \throw If the coordinates array is not set.
6380 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6381 * \throw If the connectivity data array has more than one component.
6382 * \throw If the connectivity data array has a named component.
6383 * \throw If the connectivity index data array has more than one component.
6384 * \throw If the connectivity index data array has a named component.
6385 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6386 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6387 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6389 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6392 int spaceDim=getSpaceDimension();
6393 int meshDim=getMeshDimension();
6394 if(spaceDim!=2 && spaceDim!=3)
6395 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6396 if(meshDim!=2 && meshDim!=3)
6397 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6398 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6400 int nbOfCells=getNumberOfCells();
6401 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6402 arr->alloc(nbOfCells,1);
6403 double *pt=arr->getPointer();
6404 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6405 const int *conn=_nodal_connec->getConstPointer();
6406 const int *connI=_nodal_connec_index->getConstPointer();
6407 const double *coo=_coords->getConstPointer();
6409 for(int i=0;i<nbOfCells;i++,pt++)
6411 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6414 case INTERP_KERNEL::NORM_TRI3:
6416 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6417 *pt=INTERP_KERNEL::triAspectRatio(tmp);
6420 case INTERP_KERNEL::NORM_QUAD4:
6422 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6423 *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6426 case INTERP_KERNEL::NORM_TETRA4:
6428 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6429 *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6433 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6435 conn+=connI[i+1]-connI[i];
6437 ret->setName("AspectRatio");
6438 ret->synchronizeTimeWithSupport();
6443 * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6444 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6445 * treated: INTERP_KERNEL::NORM_QUAD4.
6446 * For a cell of other type an exception is thrown.
6447 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6448 * cells and one time, lying on \a this mesh. The caller is to delete this
6449 * field using decrRef() as it is no more needed.
6450 * \throw If the coordinates array is not set.
6451 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6452 * \throw If the connectivity data array has more than one component.
6453 * \throw If the connectivity data array has a named component.
6454 * \throw If the connectivity index data array has more than one component.
6455 * \throw If the connectivity index data array has a named component.
6456 * \throw If \a this->getMeshDimension() != 2.
6457 * \throw If \a this->getSpaceDimension() != 3.
6458 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6460 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6463 int spaceDim=getSpaceDimension();
6464 int meshDim=getMeshDimension();
6466 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6468 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6469 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6471 int nbOfCells=getNumberOfCells();
6472 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6473 arr->alloc(nbOfCells,1);
6474 double *pt=arr->getPointer();
6475 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6476 const int *conn=_nodal_connec->getConstPointer();
6477 const int *connI=_nodal_connec_index->getConstPointer();
6478 const double *coo=_coords->getConstPointer();
6480 for(int i=0;i<nbOfCells;i++,pt++)
6482 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6485 case INTERP_KERNEL::NORM_QUAD4:
6487 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6488 *pt=INTERP_KERNEL::quadWarp(tmp);
6492 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6494 conn+=connI[i+1]-connI[i];
6496 ret->setName("Warp");
6497 ret->synchronizeTimeWithSupport();
6503 * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6504 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6505 * treated: INTERP_KERNEL::NORM_QUAD4.
6506 * For a cell of other type an exception is thrown.
6507 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6508 * cells and one time, lying on \a this mesh. The caller is to delete this
6509 * field using decrRef() as it is no more needed.
6510 * \throw If the coordinates array is not set.
6511 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6512 * \throw If the connectivity data array has more than one component.
6513 * \throw If the connectivity data array has a named component.
6514 * \throw If the connectivity index data array has more than one component.
6515 * \throw If the connectivity index data array has a named component.
6516 * \throw If \a this->getMeshDimension() != 2.
6517 * \throw If \a this->getSpaceDimension() != 3.
6518 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6520 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6523 int spaceDim=getSpaceDimension();
6524 int meshDim=getMeshDimension();
6526 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6528 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6529 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6531 int nbOfCells=getNumberOfCells();
6532 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6533 arr->alloc(nbOfCells,1);
6534 double *pt=arr->getPointer();
6535 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6536 const int *conn=_nodal_connec->getConstPointer();
6537 const int *connI=_nodal_connec_index->getConstPointer();
6538 const double *coo=_coords->getConstPointer();
6540 for(int i=0;i<nbOfCells;i++,pt++)
6542 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6545 case INTERP_KERNEL::NORM_QUAD4:
6547 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6548 *pt=INTERP_KERNEL::quadSkew(tmp);
6552 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6554 conn+=connI[i+1]-connI[i];
6556 ret->setName("Skew");
6557 ret->synchronizeTimeWithSupport();
6562 * 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.
6564 * \return a new instance of field containing the result. The returned instance has to be deallocated by the caller.
6566 * \sa getSkewField, getWarpField, getAspectRatioField, getEdgeRatioField
6568 MEDCouplingFieldDouble *MEDCouplingUMesh::computeDiameterField() const
6571 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME));
6573 std::set<INTERP_KERNEL::NormalizedCellType> types;
6574 ComputeAllTypesInternal(types,_nodal_connec,_nodal_connec_index);
6575 int spaceDim(getSpaceDimension()),nbCells(getNumberOfCells());
6576 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::New());
6577 arr->alloc(nbCells,1);
6578 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++)
6580 INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::DiameterCalculator> dc(INTERP_KERNEL::CellModel::GetCellModel(*it).buildInstanceOfDiameterCalulator(spaceDim));
6581 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds(giveCellsWithType(*it));
6582 dc->computeForListOfCellIdsUMeshFrmt(cellIds->begin(),cellIds->end(),_nodal_connec_index->begin(),_nodal_connec->begin(),getCoords()->begin(),arr->getPointer());
6585 ret->setName("Diameter");
6590 * This method aggregate the bbox of each cell and put it into bbox parameter.
6592 * \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)
6593 * For all other cases this input parameter is ignored.
6594 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6596 * \throw If \a this is not fully set (coordinates and connectivity).
6597 * \throw If a cell in \a this has no valid nodeId.
6598 * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6600 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6602 int mDim(getMeshDimension()),sDim(getSpaceDimension());
6603 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.
6604 return getBoundingBoxForBBTreeFast();
6605 if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6607 bool presenceOfQuadratic(false);
6608 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6610 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6611 if(cm.isQuadratic())
6612 presenceOfQuadratic=true;
6614 if(!presenceOfQuadratic)
6615 return getBoundingBoxForBBTreeFast();
6616 if(mDim==2 && sDim==2)
6617 return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6619 return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6621 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) !");
6625 * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6626 * So meshes having quadratic cells the computed bounding boxes can be invalid !
6628 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6630 * \throw If \a this is not fully set (coordinates and connectivity).
6631 * \throw If a cell in \a this has no valid nodeId.
6633 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6635 checkFullyDefined();
6636 int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6637 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6638 double *bbox(ret->getPointer());
6639 for(int i=0;i<nbOfCells*spaceDim;i++)
6641 bbox[2*i]=std::numeric_limits<double>::max();
6642 bbox[2*i+1]=-std::numeric_limits<double>::max();
6644 const double *coordsPtr(_coords->getConstPointer());
6645 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6646 for(int i=0;i<nbOfCells;i++)
6648 int offset=connI[i]+1;
6649 int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6650 for(int j=0;j<nbOfNodesForCell;j++)
6652 int nodeId=conn[offset+j];
6653 if(nodeId>=0 && nodeId<nbOfNodes)
6655 for(int k=0;k<spaceDim;k++)
6657 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6658 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6665 std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6666 throw INTERP_KERNEL::Exception(oss.str().c_str());
6673 * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6674 * useful for 2D meshes having quadratic cells
6675 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6676 * the two extremities of the arc of circle).
6678 * \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)
6679 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6680 * \throw If \a this is not fully defined.
6681 * \throw If \a this is not a mesh with meshDimension equal to 2.
6682 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6683 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6685 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6687 checkFullyDefined();
6688 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6689 if(spaceDim!=2 || mDim!=2)
6690 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!");
6691 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6692 double *bbox(ret->getPointer());
6693 const double *coords(_coords->getConstPointer());
6694 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6695 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6697 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6698 int sz(connI[1]-connI[0]-1);
6699 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6700 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6701 INTERP_KERNEL::QuadraticPolygon *pol(0);
6702 for(int j=0;j<sz;j++)
6704 int nodeId(conn[*connI+1+j]);
6705 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6707 if(!cm.isQuadratic())
6708 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6710 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6711 INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6712 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax();
6718 * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6719 * useful for 2D meshes having quadratic cells
6720 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6721 * the two extremities of the arc of circle).
6723 * \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)
6724 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6725 * \throw If \a this is not fully defined.
6726 * \throw If \a this is not a mesh with meshDimension equal to 1.
6727 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6728 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6730 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6732 checkFullyDefined();
6733 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6734 if(spaceDim!=2 || mDim!=1)
6735 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!");
6736 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6737 double *bbox(ret->getPointer());
6738 const double *coords(_coords->getConstPointer());
6739 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6740 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6742 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6743 int sz(connI[1]-connI[0]-1);
6744 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6745 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6746 INTERP_KERNEL::Edge *edge(0);
6747 for(int j=0;j<sz;j++)
6749 int nodeId(conn[*connI+1+j]);
6750 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6752 if(!cm.isQuadratic())
6753 edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6755 edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6756 const INTERP_KERNEL::Bounds& b(edge->getBounds());
6757 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6764 namespace ParaMEDMEMImpl
6769 ConnReader(const int *c, int val):_conn(c),_val(val) { }
6770 bool operator() (const int& pos) { return _conn[pos]!=_val; }
6779 ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6780 bool operator() (const int& pos) { return _conn[pos]==_val; }
6790 * This method expects that \a this is sorted by types. If not an exception will be thrown.
6791 * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6792 * \a this is composed in cell types.
6793 * The returned array is of size 3*n where n is the number of different types present in \a this.
6794 * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here.
6795 * This parameter is kept only for compatibility with other methode listed above.
6797 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6799 checkConnectivityFullyDefined();
6800 const int *conn=_nodal_connec->getConstPointer();
6801 const int *connI=_nodal_connec_index->getConstPointer();
6802 const int *work=connI;
6803 int nbOfCells=getNumberOfCells();
6804 std::size_t n=getAllGeoTypes().size();
6805 std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6806 std::set<INTERP_KERNEL::NormalizedCellType> types;
6807 for(std::size_t i=0;work!=connI+nbOfCells;i++)
6809 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6810 if(types.find(typ)!=types.end())
6812 std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6813 oss << " is not contiguous !";
6814 throw INTERP_KERNEL::Exception(oss.str().c_str());
6818 const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6819 ret[3*i+1]=(int)std::distance(work,work2);
6826 * This method is used to check that this has contiguous cell type in same order than described in \a code.
6827 * only for types cell, type node is not managed.
6828 * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6829 * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6830 * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6831 * If 2 or more same geometric type is in \a code and exception is thrown too.
6833 * This method firstly checks
6834 * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6835 * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6836 * an exception is thrown too.
6838 * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6839 * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown
6840 * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6842 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6845 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6846 std::size_t sz=code.size();
6849 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6850 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6852 bool isNoPflUsed=true;
6853 for(std::size_t i=0;i<n;i++)
6854 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6856 types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6858 if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6859 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6860 isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6863 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6866 if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6867 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6868 if(types.size()==_types.size())
6871 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6873 int *retPtr=ret->getPointer();
6874 const int *connI=_nodal_connec_index->getConstPointer();
6875 const int *conn=_nodal_connec->getConstPointer();
6876 int nbOfCells=getNumberOfCells();
6879 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6881 i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6882 int offset=(int)std::distance(connI,i);
6883 const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6884 int nbOfCellsOfCurType=(int)std::distance(i,j);
6885 if(code[3*kk+2]==-1)
6886 for(int k=0;k<nbOfCellsOfCurType;k++)
6890 int idInIdsPerType=code[3*kk+2];
6891 if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6893 const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6896 zePfl->checkAllocated();
6897 if(zePfl->getNumberOfComponents()==1)
6899 for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6901 if(*k>=0 && *k<nbOfCellsOfCurType)
6902 *retPtr=(*k)+offset;
6905 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6906 oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6907 throw INTERP_KERNEL::Exception(oss.str().c_str());
6912 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6915 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6919 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6920 oss << " should be in [0," << idsPerType.size() << ") !";
6921 throw INTERP_KERNEL::Exception(oss.str().c_str());
6930 * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6931 * 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.
6932 * 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.
6933 * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6935 * \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.
6936 * \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,
6937 * \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6938 * \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.
6939 * This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6940 * \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
6942 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6945 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6946 if(profile->getNumberOfComponents()!=1)
6947 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6948 checkConnectivityFullyDefined();
6949 const int *conn=_nodal_connec->getConstPointer();
6950 const int *connI=_nodal_connec_index->getConstPointer();
6951 int nbOfCells=getNumberOfCells();
6952 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6953 std::vector<int> typeRangeVals(1);
6954 for(const int *i=connI;i!=connI+nbOfCells;)
6956 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6957 if(std::find(types.begin(),types.end(),curType)!=types.end())
6959 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6961 types.push_back(curType);
6962 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6963 typeRangeVals.push_back((int)std::distance(connI,i));
6966 DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6967 profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6968 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6969 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6970 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6972 int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6973 code.resize(3*nbOfCastsFinal);
6974 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6975 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6976 for(int i=0;i<nbOfCastsFinal;i++)
6978 int castId=castsPresent->getIJ(i,0);
6979 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6980 idsInPflPerType2.push_back(tmp3);
6981 code[3*i]=(int)types[castId];
6982 code[3*i+1]=tmp3->getNumberOfTuples();
6983 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6984 if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6986 tmp4->copyStringInfoFrom(*profile);
6987 idsPerType2.push_back(tmp4);
6988 code[3*i+2]=(int)idsPerType2.size()-1;
6995 std::size_t sz2=idsInPflPerType2.size();
6996 idsInPflPerType.resize(sz2);
6997 for(std::size_t i=0;i<sz2;i++)
6999 DataArrayInt *locDa=idsInPflPerType2[i];
7001 idsInPflPerType[i]=locDa;
7003 std::size_t sz=idsPerType2.size();
7004 idsPerType.resize(sz);
7005 for(std::size_t i=0;i<sz;i++)
7007 DataArrayInt *locDa=idsPerType2[i];
7009 idsPerType[i]=locDa;
7014 * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
7015 * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
7016 * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
7017 * 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.
7019 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
7021 checkFullyDefined();
7022 nM1LevMesh->checkFullyDefined();
7023 if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
7024 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
7025 if(_coords!=nM1LevMesh->getCoords())
7026 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
7027 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
7028 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
7029 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
7030 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
7031 desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
7032 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
7033 tmp->setConnectivity(tmp0,tmp1);
7034 tmp->renumberCells(ret0->getConstPointer(),false);
7035 revDesc=tmp->getNodalConnectivity();
7036 revDescIndx=tmp->getNodalConnectivityIndex();
7037 DataArrayInt *ret=0;
7038 if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
7041 ret->getMaxValue(tmp2);
7043 std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
7044 throw INTERP_KERNEL::Exception(oss.str().c_str());
7049 revDescIndx->incrRef();
7052 meshnM1Old2New=ret0;
7057 * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
7058 * necessary for writing the mesh to MED file. Additionally returns a permutation array
7059 * in "Old to New" mode.
7060 * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
7061 * this array using decrRef() as it is no more needed.
7062 * \throw If the nodal connectivity of cells is not defined.
7064 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
7066 checkConnectivityFullyDefined();
7067 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
7068 renumberCells(ret->getConstPointer(),false);
7073 * This methods checks that cells are sorted by their types.
7074 * This method makes asumption (no check) that connectivity is correctly set before calling.
7076 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
7078 checkFullyDefined();
7079 const int *conn=_nodal_connec->getConstPointer();
7080 const int *connI=_nodal_connec_index->getConstPointer();
7081 int nbOfCells=getNumberOfCells();
7082 std::set<INTERP_KERNEL::NormalizedCellType> types;
7083 for(const int *i=connI;i!=connI+nbOfCells;)
7085 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7086 if(types.find(curType)!=types.end())
7088 types.insert(curType);
7089 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7095 * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
7096 * The geometric type order is specified by MED file.
7098 * \sa MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
7100 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
7102 return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7106 * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
7107 * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
7108 * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
7109 * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
7111 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7113 checkFullyDefined();
7114 const int *conn=_nodal_connec->getConstPointer();
7115 const int *connI=_nodal_connec_index->getConstPointer();
7116 int nbOfCells=getNumberOfCells();
7120 std::set<INTERP_KERNEL::NormalizedCellType> sg;
7121 for(const int *i=connI;i!=connI+nbOfCells;)
7123 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7124 const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
7125 if(isTypeExists!=orderEnd)
7127 int pos=(int)std::distance(orderBg,isTypeExists);
7131 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7135 if(sg.find(curType)==sg.end())
7137 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7148 * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
7149 * 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
7150 * 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'.
7152 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
7154 checkConnectivityFullyDefined();
7155 int nbOfCells=getNumberOfCells();
7156 const int *conn=_nodal_connec->getConstPointer();
7157 const int *connI=_nodal_connec_index->getConstPointer();
7158 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
7159 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
7160 tmpa->alloc(nbOfCells,1);
7161 tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
7162 tmpb->fillWithZero();
7163 int *tmp=tmpa->getPointer();
7164 int *tmp2=tmpb->getPointer();
7165 for(const int *i=connI;i!=connI+nbOfCells;i++)
7167 const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
7170 int pos=(int)std::distance(orderBg,where);
7172 tmp[std::distance(connI,i)]=pos;
7176 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
7177 std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
7178 oss << " has a type " << cm.getRepr() << " not in input array of type !";
7179 throw INTERP_KERNEL::Exception(oss.str().c_str());
7182 nbPerType=tmpb.retn();
7187 * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7189 * \return a new object containing the old to new correspondance.
7191 * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7193 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7195 return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7199 * 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.
7200 * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7201 * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7202 * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7204 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7206 DataArrayInt *nbPerType=0;
7207 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7208 nbPerType->decrRef();
7209 return tmpa->buildPermArrPerLevel();
7213 * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7214 * The number of cells remains unchanged after the call of this method.
7215 * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7216 * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7218 * \return the array giving the correspondance old to new.
7220 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7222 checkFullyDefined();
7224 const int *conn=_nodal_connec->getConstPointer();
7225 const int *connI=_nodal_connec_index->getConstPointer();
7226 int nbOfCells=getNumberOfCells();
7227 std::vector<INTERP_KERNEL::NormalizedCellType> types;
7228 for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7229 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7231 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7232 types.push_back(curType);
7233 for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7235 DataArrayInt *ret=DataArrayInt::New();
7236 ret->alloc(nbOfCells,1);
7237 int *retPtr=ret->getPointer();
7238 std::fill(retPtr,retPtr+nbOfCells,-1);
7240 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7242 for(const int *i=connI;i!=connI+nbOfCells;i++)
7243 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7244 retPtr[std::distance(connI,i)]=newCellId++;
7246 renumberCells(retPtr,false);
7251 * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7252 * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7253 * This method makes asumption that connectivity is correctly set before calling.
7255 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7257 checkConnectivityFullyDefined();
7258 const int *conn=_nodal_connec->getConstPointer();
7259 const int *connI=_nodal_connec_index->getConstPointer();
7260 int nbOfCells=getNumberOfCells();
7261 std::vector<MEDCouplingUMesh *> ret;
7262 for(const int *i=connI;i!=connI+nbOfCells;)
7264 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7265 int beginCellId=(int)std::distance(connI,i);
7266 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7267 int endCellId=(int)std::distance(connI,i);
7268 int sz=endCellId-beginCellId;
7269 int *cells=new int[sz];
7270 for(int j=0;j<sz;j++)
7271 cells[j]=beginCellId+j;
7272 MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7280 * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7281 * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7282 * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7284 * \return a newly allocated instance, that the caller must manage.
7285 * \throw If \a this contains more than one geometric type.
7286 * \throw If the nodal connectivity of \a this is not fully defined.
7287 * \throw If the internal data is not coherent.
7289 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7291 checkConnectivityFullyDefined();
7292 if(_types.size()!=1)
7293 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7294 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7295 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7296 ret->setCoords(getCoords());
7297 MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7300 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7301 retC->setNodalConnectivity(c);
7305 MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7307 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7308 DataArrayInt *c=0,*ci=0;
7309 convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7310 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7311 retD->setNodalConnectivity(cs,cis);
7316 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7318 checkConnectivityFullyDefined();
7319 if(_types.size()!=1)
7320 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7321 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7322 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7325 std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7326 oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7327 throw INTERP_KERNEL::Exception(oss.str().c_str());
7329 int nbCells=getNumberOfCells();
7331 int nbNodesPerCell=(int)cm.getNumberOfNodes();
7332 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7333 int *outPtr=connOut->getPointer();
7334 const int *conn=_nodal_connec->begin();
7335 const int *connI=_nodal_connec_index->begin();
7337 for(int i=0;i<nbCells;i++,connI++)
7339 if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7340 outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7343 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 << ") !";
7344 throw INTERP_KERNEL::Exception(oss.str().c_str());
7347 return connOut.retn();
7350 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7352 static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7353 checkConnectivityFullyDefined();
7354 if(_types.size()!=1)
7355 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7356 int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7358 throw INTERP_KERNEL::Exception(msg0);
7359 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7360 c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7361 int *cp(c->getPointer()),*cip(ci->getPointer());
7362 const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7364 for(int i=0;i<nbCells;i++,cip++,incip++)
7366 int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7367 int delta(stop-strt);
7370 if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7371 cp=std::copy(incp+strt,incp+stop,cp);
7373 throw INTERP_KERNEL::Exception(msg0);
7376 throw INTERP_KERNEL::Exception(msg0);
7377 cip[1]=cip[0]+delta;
7379 nodalConn=c.retn(); nodalConnIndex=ci.retn();
7383 * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7384 * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7385 * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7386 * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7387 * are not used here to avoid the build of big permutation array.
7389 * \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
7390 * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7391 * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7392 * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7393 * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7394 * output array gives for each chunck of same type the corresponding mesh id in \b ms.
7395 * \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
7396 * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7398 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7399 DataArrayInt *&szOfCellGrpOfSameType,
7400 DataArrayInt *&idInMsOfCellGrpOfSameType)
7402 std::vector<const MEDCouplingUMesh *> ms2;
7403 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7406 (*it)->checkConnectivityFullyDefined();
7410 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7411 const DataArrayDouble *refCoo=ms2[0]->getCoords();
7412 int meshDim=ms2[0]->getMeshDimension();
7413 std::vector<const MEDCouplingUMesh *> m1ssm;
7414 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7416 std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7417 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7419 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7420 ret1->alloc(0,1); ret2->alloc(0,1);
7421 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7423 if(meshDim!=(*it)->getMeshDimension())
7424 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7425 if(refCoo!=(*it)->getCoords())
7426 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7427 std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7428 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7429 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7430 for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7432 MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7433 m1ssmSingleAuto.push_back(singleCell);
7434 m1ssmSingle.push_back(singleCell);
7435 ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7438 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7439 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7440 std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7441 for(std::size_t i=0;i<m1ssm.size();i++)
7442 m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7443 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7444 szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7445 idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7450 * This method returns a newly created DataArrayInt instance.
7451 * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7453 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7455 checkFullyDefined();
7456 const int *conn=_nodal_connec->getConstPointer();
7457 const int *connIndex=_nodal_connec_index->getConstPointer();
7458 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7459 for(const int *w=begin;w!=end;w++)
7460 if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7461 ret->pushBackSilent(*w);
7466 * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7467 * are in [0:getNumberOfCells())
7469 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7471 checkFullyDefined();
7472 const int *conn=_nodal_connec->getConstPointer();
7473 const int *connI=_nodal_connec_index->getConstPointer();
7474 int nbOfCells=getNumberOfCells();
7475 std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7476 int *tmp=new int[nbOfCells];
7477 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7480 for(const int *i=connI;i!=connI+nbOfCells;i++)
7481 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7482 tmp[std::distance(connI,i)]=j++;
7484 DataArrayInt *ret=DataArrayInt::New();
7485 ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7486 ret->copyStringInfoFrom(*da);
7487 int *retPtr=ret->getPointer();
7488 const int *daPtr=da->getConstPointer();
7489 int nbOfElems=da->getNbOfElems();
7490 for(int k=0;k<nbOfElems;k++)
7491 retPtr[k]=tmp[daPtr[k]];
7497 * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7498 * This method \b works \b for mesh sorted by type.
7499 * cells whose ids is in 'idsPerGeoType' array.
7500 * This method conserves coords and name of mesh.
7502 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7504 std::vector<int> code=getDistributionOfTypes();
7505 std::size_t nOfTypesInThis=code.size()/3;
7506 int sz=0,szOfType=0;
7507 for(std::size_t i=0;i<nOfTypesInThis;i++)
7512 szOfType=code[3*i+1];
7514 for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7515 if(*work<0 || *work>=szOfType)
7517 std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7518 oss << ". It should be in [0," << szOfType << ") !";
7519 throw INTERP_KERNEL::Exception(oss.str().c_str());
7521 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7522 int *idsPtr=idsTokeep->getPointer();
7524 for(std::size_t i=0;i<nOfTypesInThis;i++)
7527 for(int j=0;j<code[3*i+1];j++)
7530 idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7531 offset+=code[3*i+1];
7533 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7534 ret->copyTinyInfoFrom(this);
7539 * This method returns a vector of size 'this->getNumberOfCells()'.
7540 * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7542 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7544 int ncell=getNumberOfCells();
7545 std::vector<bool> ret(ncell);
7546 const int *cI=getNodalConnectivityIndex()->getConstPointer();
7547 const int *c=getNodalConnectivity()->getConstPointer();
7548 for(int i=0;i<ncell;i++)
7550 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7551 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7552 ret[i]=cm.isQuadratic();
7558 * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7560 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7562 if(other->getType()!=UNSTRUCTURED)
7563 throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7564 const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7565 return MergeUMeshes(this,otherC);
7569 * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7570 * computed by averaging coordinates of cell nodes, so this method is not a right
7571 * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7572 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7573 * this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7574 * components. The caller is to delete this array using decrRef() as it is
7576 * \throw If the coordinates array is not set.
7577 * \throw If the nodal connectivity of cells is not defined.
7578 * \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7580 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7582 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7583 int spaceDim=getSpaceDimension();
7584 int nbOfCells=getNumberOfCells();
7585 ret->alloc(nbOfCells,spaceDim);
7586 ret->copyStringInfoFrom(*getCoords());
7587 double *ptToFill=ret->getPointer();
7588 const int *nodal=_nodal_connec->getConstPointer();
7589 const int *nodalI=_nodal_connec_index->getConstPointer();
7590 const double *coor=_coords->getConstPointer();
7591 for(int i=0;i<nbOfCells;i++)
7593 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7594 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7601 * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7602 * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the
7604 * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned
7605 * DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7607 * \sa MEDCouplingUMesh::getBarycenterAndOwner
7608 * \throw If \a this is not fully defined (coordinates and connectivity)
7609 * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7611 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7613 checkFullyDefined();
7614 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7615 int spaceDim=getSpaceDimension();
7616 int nbOfCells=getNumberOfCells();
7617 int nbOfNodes=getNumberOfNodes();
7618 ret->alloc(nbOfCells,spaceDim);
7619 double *ptToFill=ret->getPointer();
7620 const int *nodal=_nodal_connec->getConstPointer();
7621 const int *nodalI=_nodal_connec_index->getConstPointer();
7622 const double *coor=_coords->getConstPointer();
7623 for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7625 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7626 std::fill(ptToFill,ptToFill+spaceDim,0.);
7627 if(type!=INTERP_KERNEL::NORM_POLYHED)
7629 for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7631 if(*conn>=0 && *conn<nbOfNodes)
7632 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7635 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," << nbOfNodes << ") !";
7636 throw INTERP_KERNEL::Exception(oss.str().c_str());
7639 int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7640 if(nbOfNodesInCell>0)
7641 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7644 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7645 throw INTERP_KERNEL::Exception(oss.str().c_str());
7650 std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7652 for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7654 if(*it>=0 && *it<nbOfNodes)
7655 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7658 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," << nbOfNodes << ") !";
7659 throw INTERP_KERNEL::Exception(oss.str().c_str());
7663 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7666 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7667 throw INTERP_KERNEL::Exception(oss.str().c_str());
7675 * Returns a new DataArrayDouble holding barycenters of specified cells. The
7676 * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7677 * are specified via an array of cell ids.
7678 * \warning Validity of the specified cell ids is not checked!
7679 * Valid range is [ 0, \a this->getNumberOfCells() ).
7680 * \param [in] begin - an array of cell ids of interest.
7681 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7682 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7683 * end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7684 * caller is to delete this array using decrRef() as it is no more needed.
7685 * \throw If the coordinates array is not set.
7686 * \throw If the nodal connectivity of cells is not defined.
7688 * \if ENABLE_EXAMPLES
7689 * \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7690 * \ref py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7693 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7695 DataArrayDouble *ret=DataArrayDouble::New();
7696 int spaceDim=getSpaceDimension();
7697 int nbOfTuple=(int)std::distance(begin,end);
7698 ret->alloc(nbOfTuple,spaceDim);
7699 double *ptToFill=ret->getPointer();
7700 double *tmp=new double[spaceDim];
7701 const int *nodal=_nodal_connec->getConstPointer();
7702 const int *nodalI=_nodal_connec_index->getConstPointer();
7703 const double *coor=_coords->getConstPointer();
7704 for(const int *w=begin;w!=end;w++)
7706 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7707 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7715 * 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".
7716 * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7717 * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7718 * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7719 * This method is useful to detect 2D cells in 3D space that are not coplanar.
7721 * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7722 * \throw If spaceDim!=3 or meshDim!=2.
7723 * \throw If connectivity of \a this is invalid.
7724 * \throw If connectivity of a cell in \a this points to an invalid node.
7726 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7728 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7729 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7730 if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7731 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7732 ret->alloc(nbOfCells,4);
7733 double *retPtr(ret->getPointer());
7734 const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7735 const double *coor(_coords->begin());
7736 for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7738 double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7739 if(nodalI[1]-nodalI[0]>=3)
7741 for(int j=0;j<3;j++)
7743 int nodeId(nodal[nodalI[0]+1+j]);
7744 if(nodeId>=0 && nodeId<nbOfNodes)
7745 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7748 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7749 throw INTERP_KERNEL::Exception(oss.str().c_str());
7755 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7756 throw INTERP_KERNEL::Exception(oss.str().c_str());
7758 INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7759 retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7765 * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7768 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7771 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7772 da->checkAllocated();
7773 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7775 int nbOfTuples=da->getNumberOfTuples();
7776 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7777 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7778 c->alloc(2*nbOfTuples,1);
7779 cI->alloc(nbOfTuples+1,1);
7780 int *cp=c->getPointer();
7781 int *cip=cI->getPointer();
7783 for(int i=0;i<nbOfTuples;i++)
7785 *cp++=INTERP_KERNEL::NORM_POINT1;
7789 ret->setConnectivity(c,cI,true);
7793 * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7794 * Cells and nodes of
7795 * the first mesh precede cells and nodes of the second mesh within the result mesh.
7796 * \param [in] mesh1 - the first mesh.
7797 * \param [in] mesh2 - the second mesh.
7798 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7799 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7800 * is no more needed.
7801 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7802 * \throw If the coordinates array is not set in none of the meshes.
7803 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7804 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7806 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7808 std::vector<const MEDCouplingUMesh *> tmp(2);
7809 tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7810 return MergeUMeshes(tmp);
7814 * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7815 * Cells and nodes of
7816 * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7817 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7818 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7819 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7820 * is no more needed.
7821 * \throw If \a a.size() == 0.
7822 * \throw If \a a[ *i* ] == NULL.
7823 * \throw If the coordinates array is not set in none of the meshes.
7824 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7825 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7827 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7829 std::size_t sz=a.size();
7831 return MergeUMeshesLL(a);
7832 for(std::size_t ii=0;ii<sz;ii++)
7835 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7836 throw INTERP_KERNEL::Exception(oss.str().c_str());
7838 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7839 std::vector< const MEDCouplingUMesh * > aa(sz);
7841 for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7843 const MEDCouplingUMesh *cur=a[i];
7844 const DataArrayDouble *coo=cur->getCoords();
7846 spaceDim=coo->getNumberOfComponents();
7849 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7850 for(std::size_t i=0;i<sz;i++)
7852 bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7855 return MergeUMeshesLL(aa);
7860 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7863 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7864 std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7865 int meshDim=(*it)->getMeshDimension();
7866 int nbOfCells=(*it)->getNumberOfCells();
7867 int meshLgth=(*it++)->getMeshLength();
7868 for(;it!=a.end();it++)
7870 if(meshDim!=(*it)->getMeshDimension())
7871 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7872 nbOfCells+=(*it)->getNumberOfCells();
7873 meshLgth+=(*it)->getMeshLength();
7875 std::vector<const MEDCouplingPointSet *> aps(a.size());
7876 std::copy(a.begin(),a.end(),aps.begin());
7877 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7878 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7879 ret->setCoords(pts);
7880 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7881 c->alloc(meshLgth,1);
7882 int *cPtr=c->getPointer();
7883 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7884 cI->alloc(nbOfCells+1,1);
7885 int *cIPtr=cI->getPointer();
7889 for(it=a.begin();it!=a.end();it++)
7891 int curNbOfCell=(*it)->getNumberOfCells();
7892 const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7893 const int *curC=(*it)->_nodal_connec->getConstPointer();
7894 cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7895 for(int j=0;j<curNbOfCell;j++)
7897 const int *src=curC+curCI[j];
7899 for(;src!=curC+curCI[j+1];src++,cPtr++)
7907 offset+=curCI[curNbOfCell];
7908 offset2+=(*it)->getNumberOfNodes();
7911 ret->setConnectivity(c,cI,true);
7918 * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7919 * dimension and sharing the node coordinates array.
7920 * All cells of the first mesh precede all cells of the second mesh
7921 * within the result mesh.
7922 * \param [in] mesh1 - the first mesh.
7923 * \param [in] mesh2 - the second mesh.
7924 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7925 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7926 * is no more needed.
7927 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7928 * \throw If the meshes do not share the node coordinates array.
7929 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7930 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7932 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7934 std::vector<const MEDCouplingUMesh *> tmp(2);
7935 tmp[0]=mesh1; tmp[1]=mesh2;
7936 return MergeUMeshesOnSameCoords(tmp);
7940 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7941 * dimension and sharing the node coordinates array.
7942 * All cells of the *i*-th mesh precede all cells of the
7943 * (*i*+1)-th mesh within the result mesh.
7944 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7945 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7946 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7947 * is no more needed.
7948 * \throw If \a a.size() == 0.
7949 * \throw If \a a[ *i* ] == NULL.
7950 * \throw If the meshes do not share the node coordinates array.
7951 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7952 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7954 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7957 throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7958 for(std::size_t ii=0;ii<meshes.size();ii++)
7961 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7962 throw INTERP_KERNEL::Exception(oss.str().c_str());
7964 const DataArrayDouble *coords=meshes.front()->getCoords();
7965 int meshDim=meshes.front()->getMeshDimension();
7966 std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7968 int meshIndexLgth=0;
7969 for(;iter!=meshes.end();iter++)
7971 if(coords!=(*iter)->getCoords())
7972 throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7973 if(meshDim!=(*iter)->getMeshDimension())
7974 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7975 meshLgth+=(*iter)->getMeshLength();
7976 meshIndexLgth+=(*iter)->getNumberOfCells();
7978 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7979 nodal->alloc(meshLgth,1);
7980 int *nodalPtr=nodal->getPointer();
7981 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7982 nodalIndex->alloc(meshIndexLgth+1,1);
7983 int *nodalIndexPtr=nodalIndex->getPointer();
7985 for(iter=meshes.begin();iter!=meshes.end();iter++)
7987 const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7988 const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7989 int nbOfCells=(*iter)->getNumberOfCells();
7990 int meshLgth2=(*iter)->getMeshLength();
7991 nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7992 if(iter!=meshes.begin())
7993 nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7995 nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7998 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7999 ret->setName("merge");
8000 ret->setMeshDimension(meshDim);
8001 ret->setConnectivity(nodal,nodalIndex,true);
8002 ret->setCoords(coords);
8007 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
8008 * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
8009 * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
8010 * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
8011 * New" mode are returned for each input mesh.
8012 * \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
8013 * \param [in] compType - specifies a cell comparison technique. For meaning of its
8014 * valid values [0,1,2], see zipConnectivityTraducer().
8015 * \param [in,out] corr - an array of DataArrayInt, of the same size as \a
8016 * meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
8017 * mesh. The caller is to delete each of the arrays using decrRef() as it is
8019 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
8020 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8021 * is no more needed.
8022 * \throw If \a meshes.size() == 0.
8023 * \throw If \a meshes[ *i* ] == NULL.
8024 * \throw If the meshes do not share the node coordinates array.
8025 * \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
8026 * \throw If the \a meshes are of different dimension (getMeshDimension()).
8027 * \throw If the nodal connectivity of cells of any of \a meshes is not defined.
8028 * \throw If the nodal connectivity any of \a meshes includes an invalid id.
8030 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
8032 //All checks are delegated to MergeUMeshesOnSameCoords
8033 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
8034 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
8035 corr.resize(meshes.size());
8036 std::size_t nbOfMeshes=meshes.size();
8038 const int *o2nPtr=o2n->getConstPointer();
8039 for(std::size_t i=0;i<nbOfMeshes;i++)
8041 DataArrayInt *tmp=DataArrayInt::New();
8042 int curNbOfCells=meshes[i]->getNumberOfCells();
8043 tmp->alloc(curNbOfCells,1);
8044 std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
8045 offset+=curNbOfCells;
8046 tmp->setName(meshes[i]->getName());
8053 * Makes all given meshes share the nodal connectivity array. The common connectivity
8054 * array is created by concatenating the connectivity arrays of all given meshes. All
8055 * the given meshes must be of the same space dimension but dimension of cells **can
8056 * differ**. This method is particulary useful in MEDLoader context to build a \ref
8057 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8058 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8059 * \param [in,out] meshes - a vector of meshes to update.
8060 * \throw If any of \a meshes is NULL.
8061 * \throw If the coordinates array is not set in any of \a meshes.
8062 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8063 * \throw If \a meshes are of different space dimension.
8065 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
8067 std::size_t sz=meshes.size();
8070 std::vector< const DataArrayDouble * > coords(meshes.size());
8071 std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
8072 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
8076 (*it)->checkConnectivityFullyDefined();
8077 const DataArrayDouble *coo=(*it)->getCoords();
8082 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8083 oss << " has no coordinate array defined !";
8084 throw INTERP_KERNEL::Exception(oss.str().c_str());
8089 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8090 oss << " is null !";
8091 throw INTERP_KERNEL::Exception(oss.str().c_str());
8094 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
8095 std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
8096 int offset=(*it)->getNumberOfNodes();
8097 (*it++)->setCoords(res);
8098 for(;it!=meshes.end();it++)
8100 int oldNumberOfNodes=(*it)->getNumberOfNodes();
8101 (*it)->setCoords(res);
8102 (*it)->shiftNodeNumbersInConn(offset);
8103 offset+=oldNumberOfNodes;
8108 * Merges nodes coincident with a given precision within all given meshes that share
8109 * the nodal connectivity array. The given meshes **can be of different** mesh
8110 * dimension. This method is particulary useful in MEDLoader context to build a \ref
8111 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8112 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8113 * \param [in,out] meshes - a vector of meshes to update.
8114 * \param [in] eps - the precision used to detect coincident nodes (infinite norm).
8115 * \throw If any of \a meshes is NULL.
8116 * \throw If the \a meshes do not share the same node coordinates array.
8117 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8119 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
8123 std::set<const DataArrayDouble *> s;
8124 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8127 s.insert((*it)->getCoords());
8130 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 !";
8131 throw INTERP_KERNEL::Exception(oss.str().c_str());
8136 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 !";
8137 throw INTERP_KERNEL::Exception(oss.str().c_str());
8139 const DataArrayDouble *coo=*(s.begin());
8143 DataArrayInt *comm,*commI;
8144 coo->findCommonTuples(eps,-1,comm,commI);
8145 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
8146 int oldNbOfNodes=coo->getNumberOfTuples();
8148 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
8149 if(oldNbOfNodes==newNbOfNodes)
8151 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
8152 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8154 (*it)->renumberNodesInConn(o2n->getConstPointer());
8155 (*it)->setCoords(newCoords);
8160 * 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.
8161 * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
8162 * \param isQuad specifies the policy of connectivity.
8163 * @ret in/out parameter in which the result will be append
8165 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
8167 INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
8168 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
8169 ret.push_back(cm.getExtrudedType());
8170 int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
8173 case INTERP_KERNEL::NORM_POINT1:
8175 ret.push_back(connBg[1]);
8176 ret.push_back(connBg[1]+nbOfNodesPerLev);
8179 case INTERP_KERNEL::NORM_SEG2:
8181 int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
8182 ret.insert(ret.end(),conn,conn+4);
8185 case INTERP_KERNEL::NORM_SEG3:
8187 int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8188 ret.insert(ret.end(),conn,conn+8);
8191 case INTERP_KERNEL::NORM_QUAD4:
8193 int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8194 ret.insert(ret.end(),conn,conn+8);
8197 case INTERP_KERNEL::NORM_TRI3:
8199 int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8200 ret.insert(ret.end(),conn,conn+6);
8203 case INTERP_KERNEL::NORM_TRI6:
8205 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,
8206 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8207 ret.insert(ret.end(),conn,conn+15);
8210 case INTERP_KERNEL::NORM_QUAD8:
8213 connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8214 connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8215 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8217 ret.insert(ret.end(),conn,conn+20);
8220 case INTERP_KERNEL::NORM_POLYGON:
8222 std::back_insert_iterator< std::vector<int> > ii(ret);
8223 std::copy(connBg+1,connEnd,ii);
8225 std::reverse_iterator<const int *> rConnBg(connEnd);
8226 std::reverse_iterator<const int *> rConnEnd(connBg+1);
8227 std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8228 std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8229 for(std::size_t i=0;i<nbOfRadFaces;i++)
8232 int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8233 std::copy(conn,conn+4,ii);
8238 throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8243 * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8245 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8248 double v[3]={0.,0.,0.};
8249 std::size_t sz=std::distance(begin,end);
8254 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];
8255 v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8256 v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8258 double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8260 // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8261 // SEG3 forming a circle):
8262 if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8264 v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8265 for(std::size_t j=0;j<sz;j++)
8267 if (j%2) // current point i is quadratic, next point i+1 is standard
8270 ip1 = (j+1)%sz; // ip1 = "i+1"
8272 else // current point i is standard, next point i+1 is quadratic
8277 v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8278 v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8279 v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8281 ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8287 * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8289 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8291 std::vector<std::pair<int,int> > edges;
8292 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8293 const int *bgFace=begin;
8294 for(std::size_t i=0;i<nbOfFaces;i++)
8296 const int *endFace=std::find(bgFace+1,end,-1);
8297 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8298 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8300 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8301 if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8303 edges.push_back(p1);
8307 return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8311 * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8313 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8315 double vec0[3],vec1[3];
8316 std::size_t sz=std::distance(begin,end);
8318 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8319 int nbOfNodes=(int)sz/2;
8320 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8321 const double *pt0=coords+3*begin[0];
8322 const double *pt1=coords+3*begin[nbOfNodes];
8323 vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8324 return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8327 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8329 std::size_t sz=std::distance(begin,end);
8330 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8331 std::size_t nbOfNodes(sz/2);
8332 std::copy(begin,end,(int *)tmp);
8333 for(std::size_t j=1;j<nbOfNodes;j++)
8335 begin[j]=tmp[nbOfNodes-j];
8336 begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8340 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8342 std::size_t sz=std::distance(begin,end);
8344 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8345 double vec0[3],vec1[3];
8346 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8347 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];
8348 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;
8351 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8353 std::size_t sz=std::distance(begin,end);
8355 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8357 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8358 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8359 return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8363 * 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 )
8364 * 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
8367 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8368 * \param [in] coords the coordinates with nb of components exactly equal to 3
8369 * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8370 * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8371 * \param [out] res the result is put at the end of the vector without any alteration of the data.
8373 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8375 int nbFaces=std::count(begin+1,end,-1)+1;
8376 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8377 double *vPtr=v->getPointer();
8378 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8379 double *pPtr=p->getPointer();
8380 const int *stFaceConn=begin+1;
8381 for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8383 const int *endFaceConn=std::find(stFaceConn,end,-1);
8384 ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8385 stFaceConn=endFaceConn+1;
8387 pPtr=p->getPointer(); vPtr=v->getPointer();
8388 DataArrayInt *comm1=0,*commI1=0;
8389 v->findCommonTuples(eps,-1,comm1,commI1);
8390 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8391 const int *comm1Ptr=comm1->getConstPointer();
8392 const int *commI1Ptr=commI1->getConstPointer();
8393 int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8394 res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8396 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8397 mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8398 mm->finishInsertingCells();
8400 for(int i=0;i<nbOfGrps1;i++)
8402 int vecId=comm1Ptr[commI1Ptr[i]];
8403 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8404 DataArrayInt *comm2=0,*commI2=0;
8405 tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8406 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8407 const int *comm2Ptr=comm2->getConstPointer();
8408 const int *commI2Ptr=commI2->getConstPointer();
8409 int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8410 for(int j=0;j<nbOfGrps2;j++)
8412 if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8414 res->insertAtTheEnd(begin,end);
8415 res->pushBackSilent(-1);
8419 int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8420 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8421 ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8422 DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8423 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8424 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8425 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8426 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8427 const int *idsNodePtr=idsNode->getConstPointer();
8428 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];
8429 double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8430 double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8431 if(std::abs(norm)>eps)
8433 double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8434 mm3->rotate(center,vec,angle);
8436 mm3->changeSpaceDimension(2);
8437 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8438 const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8439 const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8440 int nbOfCells=mm4->getNumberOfCells();
8441 for(int k=0;k<nbOfCells;k++)
8444 for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8445 res->pushBackSilent(idsNodePtr[*work]);
8446 res->pushBackSilent(-1);
8451 res->popBackSilent();
8455 * 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
8456 * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8458 * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8459 * \param [in] coords coordinates expected to have 3 components.
8460 * \param [in] begin start of the nodal connectivity of the face.
8461 * \param [in] end end of the nodal connectivity (excluded) of the face.
8462 * \param [out] v the normalized vector of size 3
8463 * \param [out] p the pos of plane
8465 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8467 std::size_t nbPoints=std::distance(begin,end);
8469 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8470 double vec[3]={0.,0.,0.};
8472 bool refFound=false;
8473 for(;j<nbPoints-1 && !refFound;j++)
8475 vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8476 vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8477 vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8478 double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8482 vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8485 for(std::size_t i=j;i<nbPoints-1;i++)
8488 curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8489 curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8490 curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8491 double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8494 curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8495 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];
8496 norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8499 v[0]/=norm; v[1]/=norm; v[2]/=norm;
8500 *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8504 throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8508 * This method tries to obtain a well oriented polyhedron.
8509 * If the algorithm fails, an exception will be thrown.
8511 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8513 std::list< std::pair<int,int> > edgesOK,edgesFinished;
8514 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8515 std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8517 int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8518 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8519 for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8521 while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8524 std::size_t smthChanged=0;
8525 for(std::size_t i=0;i<nbOfFaces;i++)
8527 endFace=std::find(bgFace+1,end,-1);
8528 nbOfEdgesInFace=std::distance(bgFace,endFace);
8532 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8534 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8535 std::pair<int,int> p2(p1.second,p1.first);
8536 bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8537 bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8538 if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8543 std::reverse(bgFace+1,endFace);
8544 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8546 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8547 std::pair<int,int> p2(p1.second,p1.first);
8548 if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8549 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8550 if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8551 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8552 std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8553 if(it!=edgesOK.end())
8556 edgesFinished.push_back(p1);
8559 edgesOK.push_back(p1);
8566 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8568 if(!edgesOK.empty())
8569 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8570 if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8571 {//not lucky ! The first face was not correctly oriented : reorient all faces...
8573 for(std::size_t i=0;i<nbOfFaces;i++)
8575 endFace=std::find(bgFace+1,end,-1);
8576 std::reverse(bgFace+1,endFace);
8582 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8584 int nbOfNodesExpected(skin->getNumberOfNodes());
8585 const int *n2oPtr(n2o->getConstPointer());
8586 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8587 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8588 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8589 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8590 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8591 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8592 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_POLYGON;
8593 if(nbOfNodesExpected<1)
8595 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8596 *work++=n2oPtr[prevNode];
8597 for(int i=1;i<nbOfNodesExpected;i++)
8599 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8601 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8602 conn.erase(prevNode);
8605 int curNode(*(conn.begin()));
8606 *work++=n2oPtr[curNode];
8607 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8608 shar.erase(prevCell);
8611 prevCell=*(shar.begin());
8615 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8618 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8621 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8626 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8628 int nbOfNodesExpected(skin->getNumberOfNodes());
8629 int nbOfTurn(nbOfNodesExpected/2);
8630 const int *n2oPtr(n2o->getConstPointer());
8631 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8632 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8633 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8634 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8635 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8636 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8637 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_QPOLYG;
8638 if(nbOfNodesExpected<1)
8640 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8641 *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8642 for(int i=1;i<nbOfTurn;i++)
8644 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8646 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8647 conn.erase(prevNode);
8650 int curNode(*(conn.begin()));
8651 *work=n2oPtr[curNode];
8652 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8653 shar.erase(prevCell);
8656 int curCell(*(shar.begin()));
8657 work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8663 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8666 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8669 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8675 * This method makes the assumption spacedimension == meshdimension == 2.
8676 * This method works only for linear cells.
8678 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8680 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8682 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8683 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8684 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8685 int oldNbOfNodes(skin->getNumberOfNodes());
8686 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8687 int nbOfNodesExpected(skin->getNumberOfNodes());
8688 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8689 int nbCells(skin->getNumberOfCells());
8690 if(nbCells==nbOfNodesExpected)
8691 return buildUnionOf2DMeshLinear(skin,n2o);
8692 else if(2*nbCells==nbOfNodesExpected)
8693 return buildUnionOf2DMeshQuadratic(skin,n2o);
8695 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8699 * This method makes the assumption spacedimension == meshdimension == 3.
8700 * This method works only for linear cells.
8702 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8704 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8706 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8707 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8708 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8709 const int *conn=m->getNodalConnectivity()->getConstPointer();
8710 const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8711 int nbOfCells=m->getNumberOfCells();
8712 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8713 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED;
8716 work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8717 for(int i=1;i<nbOfCells;i++)
8720 work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8726 * \brief Creates a graph of cell neighbors
8727 * \return MEDCouplingSkyLineArray * - an sky line array the user should delete.
8728 * In the sky line array, graph arcs are stored in terms of (index,value) notation.
8730 * - index: 0 3 5 6 6
8731 * - value: 1 2 3 2 3 3
8732 * means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8733 * Arcs are not doubled but reflexive (1,1) arcs are present for each cell
8735 MEDCouplingSkyLineArray *MEDCouplingUMesh::generateGraph() const
8737 checkConnectivityFullyDefined();
8739 int meshDim = this->getMeshDimension();
8740 ParaMEDMEM::DataArrayInt* indexr=ParaMEDMEM::DataArrayInt::New();
8741 ParaMEDMEM::DataArrayInt* revConn=ParaMEDMEM::DataArrayInt::New();
8742 this->getReverseNodalConnectivity(revConn,indexr);
8743 const int* indexr_ptr=indexr->getConstPointer();
8744 const int* revConn_ptr=revConn->getConstPointer();
8746 const ParaMEDMEM::DataArrayInt* index;
8747 const ParaMEDMEM::DataArrayInt* conn;
8748 conn=this->getNodalConnectivity(); // it includes a type as the 1st element!!!
8749 index=this->getNodalConnectivityIndex();
8750 int nbCells=this->getNumberOfCells();
8751 const int* index_ptr=index->getConstPointer();
8752 const int* conn_ptr=conn->getConstPointer();
8754 //creating graph arcs (cell to cell relations)
8755 //arcs are stored in terms of (index,value) notation
8758 // means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8759 // in present version arcs are not doubled but reflexive (1,1) arcs are present for each cell
8761 //warning here one node have less than or equal effective number of cell with it
8762 //but cell could have more than effective nodes
8763 //because other equals nodes in other domain (with other global inode)
8764 std::vector <int> cell2cell_index(nbCells+1,0);
8765 std::vector <int> cell2cell;
8766 cell2cell.reserve(3*nbCells);
8768 for (int icell=0; icell<nbCells;icell++)
8770 std::map<int,int > counter;
8771 for (int iconn=index_ptr[icell]+1; iconn<index_ptr[icell+1];iconn++)
8773 int inode=conn_ptr[iconn];
8774 for (int iconnr=indexr_ptr[inode]; iconnr<indexr_ptr[inode+1];iconnr++)
8776 int icell2=revConn_ptr[iconnr];
8777 std::map<int,int>::iterator iter=counter.find(icell2);
8778 if (iter!=counter.end()) (iter->second)++;
8779 else counter.insert(std::make_pair(icell2,1));
8782 for (std::map<int,int>::const_iterator iter=counter.begin();
8783 iter!=counter.end(); iter++)
8784 if (iter->second >= meshDim)
8786 cell2cell_index[icell+1]++;
8787 cell2cell.push_back(iter->first);
8792 cell2cell_index[0]=0;
8793 for (int icell=0; icell<nbCells;icell++)
8794 cell2cell_index[icell+1]=cell2cell_index[icell]+cell2cell_index[icell+1];
8796 //filling up index and value to create skylinearray structure
8797 MEDCouplingSkyLineArray* array=new MEDCouplingSkyLineArray(cell2cell_index,cell2cell);
8802 * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8803 * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8805 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8809 for(int i=0;i<nbOfNodesInCell;i++)
8810 w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8811 else if(spaceDim==2)
8813 for(int i=0;i<nbOfNodesInCell;i++)
8815 w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8820 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8823 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8825 int nbOfCells=getNumberOfCells();
8827 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8828 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};
8829 ofs << " <" << getVTKDataSetType() << ">\n";
8830 ofs << " <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8831 ofs << " <PointData>\n" << pointData << std::endl;
8832 ofs << " </PointData>\n";
8833 ofs << " <CellData>\n" << cellData << std::endl;
8834 ofs << " </CellData>\n";
8835 ofs << " <Points>\n";
8836 if(getSpaceDimension()==3)
8837 _coords->writeVTK(ofs,8,"Points",byteData);
8840 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8841 coo->writeVTK(ofs,8,"Points",byteData);
8843 ofs << " </Points>\n";
8844 ofs << " <Cells>\n";
8845 const int *cPtr=_nodal_connec->getConstPointer();
8846 const int *cIPtr=_nodal_connec_index->getConstPointer();
8847 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8848 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8849 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8850 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8851 int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8852 int szFaceOffsets=0,szConn=0;
8853 for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8856 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8859 *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8860 w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8864 int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8865 *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8866 std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8867 *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8868 w4=std::copy(c.begin(),c.end(),w4);
8871 types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8872 types->writeVTK(ofs,8,"UInt8","types",byteData);
8873 offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8874 if(szFaceOffsets!=0)
8875 {//presence of Polyhedra
8876 connectivity->reAlloc(szConn);
8877 faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8878 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8879 w1=faces->getPointer();
8880 for(int i=0;i<nbOfCells;i++)
8881 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8883 int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8885 const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8886 for(int j=0;j<nbFaces;j++)
8888 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8889 *w1++=(int)std::distance(w6,w5);
8890 w1=std::copy(w6,w5,w1);
8894 faces->writeVTK(ofs,8,"Int32","faces",byteData);
8896 connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8897 ofs << " </Cells>\n";
8898 ofs << " </Piece>\n";
8899 ofs << " </" << getVTKDataSetType() << ">\n";
8902 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8904 stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8906 { stream << " Not set !"; return ; }
8907 stream << " Mesh dimension : " << _mesh_dim << ".";
8911 { stream << " No coordinates set !"; return ; }
8912 if(!_coords->isAllocated())
8913 { stream << " Coordinates set but not allocated !"; return ; }
8914 stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8915 stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8916 if(!_nodal_connec_index)
8917 { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8918 if(!_nodal_connec_index->isAllocated())
8919 { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8920 int lgth=_nodal_connec_index->getNumberOfTuples();
8921 int cpt=_nodal_connec_index->getNumberOfComponents();
8922 if(cpt!=1 || lgth<1)
8924 stream << std::endl << "Number of cells : " << lgth-1 << ".";
8927 std::string MEDCouplingUMesh::getVTKDataSetType() const
8929 return std::string("UnstructuredGrid");
8932 std::string MEDCouplingUMesh::getVTKFileExtension() const
8934 return std::string("vtu");
8938 * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8939 * returns a result mesh constituted by polygons.
8940 * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8941 * all nodes from m2.
8942 * The meshes should be in 2D space. In
8943 * addition, returns two arrays mapping cells of the result mesh to cells of the input
8945 * \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
8946 * 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)
8947 * \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
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] eps - precision used to detect coincident mesh entities.
8950 * \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8951 * cell an id of the cell of \a m1 it comes from. The caller is to delete
8952 * this array using decrRef() as it is no more needed.
8953 * \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8954 * cell an id of the cell of \a m2 it comes from. -1 value means that a
8955 * result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8956 * any cell of \a m2. The caller is to delete this array using decrRef() as
8957 * it is no more needed.
8958 * \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8959 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8960 * is no more needed.
8961 * \throw If the coordinates array is not set in any of the meshes.
8962 * \throw If the nodal connectivity of cells is not defined in any of the meshes.
8963 * \throw If any of the meshes is not a 2D mesh in 2D space.
8965 * \sa conformize2D, mergeNodes
8967 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8968 double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8971 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
8972 m1->checkFullyDefined();
8973 m2->checkFullyDefined();
8974 if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8975 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!");
8977 // Step 1: compute all edge intersections (new nodes)
8978 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8979 MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
8980 DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8981 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
8982 IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
8983 m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8984 addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
8985 revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8986 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8987 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8989 // Step 2: re-order newly created nodes according to the ordering found in m2
8990 std::vector< std::vector<int> > intersectEdge2;
8991 BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8992 subDiv2.clear(); dd5=0; dd6=0;
8995 std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8996 std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8997 BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8998 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
9000 // Step 4: Prepare final result:
9001 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9002 addCooDa->alloc((int)(addCoo.size())/2,2);
9003 std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
9004 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
9005 addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
9006 std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
9007 std::vector<const DataArrayDouble *> coordss(4);
9008 coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
9009 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
9010 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
9011 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
9012 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
9013 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
9014 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
9015 ret->setConnectivity(conn,connI,true);
9016 ret->setCoords(coo);
9017 cellNb1=c1.retn(); cellNb2=c2.retn();
9023 bool IsColinearOfACellOf(const std::vector< std::vector<int> >& intersectEdge1, const std::vector<int>& candidates, int start, int stop, int& retVal)
9025 if(candidates.empty())
9027 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
9029 const std::vector<int>& pool(intersectEdge1[*it]);
9030 int tmp[2]; tmp[0]=start; tmp[1]=stop;
9031 if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9036 tmp[0]=stop; tmp[1]=start;
9037 if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9046 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,
9047 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInRetColinear, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInMesh1DForIdsInRetColinear)
9049 idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1);
9050 idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1);
9051 int nCells(mesh1D->getNumberOfCells());
9052 if(nCells!=(int)intersectEdge2.size())
9053 throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
9054 const DataArrayDouble *coo2(mesh1D->getCoords());
9055 const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
9056 const double *coo2Ptr(coo2->begin());
9057 int offset1(coords1->getNumberOfTuples());
9058 int offset2(offset1+coo2->getNumberOfTuples());
9059 int offset3(offset2+addCoo.size()/2);
9060 std::vector<double> addCooQuad;
9061 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
9062 int tmp[4],cicnt(0),kk(0);
9063 for(int i=0;i<nCells;i++)
9065 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9066 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
9067 const std::vector<int>& subEdges(intersectEdge2[i]);
9068 int nbSubEdge(subEdges.size()/2);
9069 for(int j=0;j<nbSubEdge;j++,kk++)
9071 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));
9072 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
9073 INTERP_KERNEL::Edge *e2Ptr(e2);
9074 std::map<int,int>::const_iterator itm;
9075 if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
9077 tmp[0]=INTERP_KERNEL::NORM_SEG3;
9078 itm=mergedNodes.find(subEdges[2*j]);
9079 tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9080 itm=mergedNodes.find(subEdges[2*j+1]);
9081 tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9082 tmp[3]=offset3+(int)addCooQuad.size()/2;
9084 e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2);
9086 cOut->insertAtTheEnd(tmp,tmp+4);
9087 ciOut->pushBackSilent(cicnt);
9091 tmp[0]=INTERP_KERNEL::NORM_SEG2;
9092 itm=mergedNodes.find(subEdges[2*j]);
9093 tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9094 itm=mergedNodes.find(subEdges[2*j+1]);
9095 tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9097 cOut->insertAtTheEnd(tmp,tmp+3);
9098 ciOut->pushBackSilent(cicnt);
9101 if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00))
9103 idsInRetColinear->pushBackSilent(kk);
9104 idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00);
9109 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
9110 ret->setConnectivity(cOut,ciOut,true);
9111 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr3(DataArrayDouble::New());
9112 arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9113 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
9114 std::vector<const DataArrayDouble *> coordss(4);
9115 coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
9116 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
9117 ret->setCoords(arr);
9121 MEDCouplingUMesh *BuildRefined2DCellLinear(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9123 std::vector<int> allEdges;
9124 for(const int *it2(descBg);it2!=descEnd;it2++)
9126 const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9128 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9130 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9132 std::size_t nb(allEdges.size());
9134 throw INTERP_KERNEL::Exception("BuildRefined2DCellLinear : internal error 1 !");
9135 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9136 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9137 ret->setCoords(coords);
9138 ret->allocateCells(1);
9139 std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9140 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9141 connOut[kk]=allEdges[2*kk];
9142 ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]);
9146 MEDCouplingUMesh *BuildRefined2DCellQuadratic(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9148 const int *c(mesh2D->getNodalConnectivity()->begin()),*ci(mesh2D->getNodalConnectivityIndex()->begin());
9149 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[cellIdInMesh2D]]));
9151 unsigned sz(cm.getNumberOfSons2(c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1));
9152 if(sz!=std::distance(descBg,descEnd))
9153 throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 1 !");
9154 INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]]);
9155 std::vector<int> allEdges,centers;
9156 const double *coordsPtr(coords->begin());
9157 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
9158 int offset(coords->getNumberOfTuples());
9159 for(const int *it2(descBg);it2!=descEnd;it2++,ii++)
9161 INTERP_KERNEL::NormalizedCellType typeOfSon;
9162 cm.fillSonCellNodalConnectivity2(ii,c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1,tmpPtr,typeOfSon);
9163 const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9165 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9167 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9169 centers.push_back(tmpPtr[2]);//special case where no subsplit of edge -> reuse the original center.
9171 {//the current edge has been subsplit -> create corresponding centers.
9172 std::size_t nbOfCentersToAppend(edge1.size()/2);
9173 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9174 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpPtr,coordsPtr,m));
9175 std::vector<int>::const_iterator it3(allEdges.end()-edge1.size());
9176 for(std::size_t k=0;k<nbOfCentersToAppend;k++)
9179 const double *aa(coordsPtr+2*(*it3++));
9180 const double *bb(coordsPtr+2*(*it3++));
9181 ee->getMiddleOfPoints(aa,bb,tmpp);
9182 addCoo->insertAtTheEnd(tmpp,tmpp+2);
9183 centers.push_back(offset+k);
9187 std::size_t nb(allEdges.size());
9189 throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 2 !");
9190 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9191 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9193 ret->setCoords(coords);
9196 addCoo->rearrange(2);
9197 addCoo=DataArrayDouble::Aggregate(coords,addCoo);
9198 ret->setCoords(addCoo);
9200 ret->allocateCells(1);
9201 std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9202 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9203 connOut[kk]=allEdges[2*kk];
9204 connOut.insert(connOut.end(),centers.begin(),centers.end());
9205 ret->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,connOut.size(),&connOut[0]);
9210 * This method creates a refinement of a cell in \a mesh2D. Those cell is defined by descending connectivity and the sorted subdivided nodal connectivity
9213 * \param [in] mesh2D - The origin 2D mesh. \b Warning \b coords are not those of \a mesh2D. But mesh2D->getCoords()==coords[:mesh2D->getNumberOfNodes()]
9215 MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9217 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(mesh2D->getTypeOfCell(cellIdInMesh2D)));
9218 if(!cm.isQuadratic())
9219 return BuildRefined2DCellLinear(coords,descBg,descEnd,intersectEdge1);
9221 return BuildRefined2DCellQuadratic(coords,mesh2D,cellIdInMesh2D,descBg,descEnd,intersectEdge1);
9224 void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector<int>& conn, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edges)
9227 for(std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >::const_iterator it=edges.begin();it!=edges.end();it++)
9229 const INTERP_KERNEL::Edge *ee(*it);
9230 if(dynamic_cast<const INTERP_KERNEL::EdgeArcCircle *>(ee))
9234 mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]);
9237 const double *coo(mesh2D->getCoords()->begin());
9238 std::size_t sz(conn.size());
9239 std::vector<double> addCoo;
9240 std::vector<int> conn2(conn);
9241 int offset(mesh2D->getNumberOfNodes());
9242 for(std::size_t i=0;i<sz;i++)
9245 edges[(i+1)%sz]->getMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);// tony a chier i+1 -> i
9246 addCoo.insert(addCoo.end(),tmp,tmp+2);
9247 conn2.push_back(offset+(int)i);
9249 mesh2D->getCoords()->rearrange(1);
9250 mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size());
9251 mesh2D->getCoords()->rearrange(2);
9252 mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]);
9257 * \b WARNING edges in out1 coming from \a splitMesh1D are \b NOT oriented because only used for equation of curve.
9259 * This method cuts in 2 parts the input 2D cell given using boundaries description (\a edge1Bis and \a edge1BisPtr) using
9260 * a set of edges defined in \a splitMesh1D.
9262 void BuildMesh2DCutInternal2(const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& edge1Bis, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edge1BisPtr,
9263 std::vector< std::vector<int> >& out0, std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& out1)
9265 std::size_t nb(edge1Bis.size()/2);
9266 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9267 int iEnd(splitMesh1D->getNumberOfCells());
9269 throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal2 : internal error ! input 1D mesh must have at least one cell !");
9271 const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9272 for(ii=0;ii<nb && edge1Bis[2*ii]!=cSplitPtr[ciSplitPtr[0]+1];ii++);
9273 for(jj=ii;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd-1]+2];jj++);
9276 {//the edges splitMesh1D[iStart:iEnd] does not fully cut the current 2D cell -> single output cell
9277 out0.resize(1); out1.resize(1);
9278 std::vector<int>& connOut(out0[0]);
9279 connOut.resize(nbOfEdgesOf2DCellSplit);
9280 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr(out1[0]);
9281 edgesPtr.resize(nbOfEdgesOf2DCellSplit);
9282 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9284 connOut[kk]=edge1Bis[2*kk];
9285 edgesPtr[kk]=edge1BisPtr[2*kk];
9290 // [i,iEnd[ contains the
9291 out0.resize(2); out1.resize(2);
9292 std::vector<int>& connOutLeft(out0[0]);
9293 std::vector<int>& connOutRight(out0[1]);//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1]
9294 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eleft(out1[0]);
9295 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eright(out1[1]);
9296 for(std::size_t k=ii;k<jj+1;k++)
9297 { connOutLeft.push_back(edge1Bis[2*k+1]); eleft.push_back(edge1BisPtr[2*k+1]); }
9298 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > ees(iEnd);
9299 for(int ik=0;ik<iEnd;ik++)
9301 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9302 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9305 for(int ik=iEnd-1;ik>=0;ik--)
9306 connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]);
9307 for(std::size_t k=jj+1;k<nbOfEdgesOf2DCellSplit+ii;k++)
9308 { connOutRight.push_back(edge1Bis[2*k+1]); eright.push_back(edge1BisPtr[2*k+1]); }
9309 eleft.insert(eleft.end(),ees.rbegin(),ees.rend());
9310 for(int ik=0;ik<iEnd;ik++)
9311 connOutRight.push_back(cSplitPtr[ciSplitPtr[ik]+2]);
9312 eright.insert(eright.end(),ees.begin(),ees.end());
9324 CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9326 std::vector<int> _edges;
9327 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > _edges_ptr;
9330 CellInfo::CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr)
9332 std::size_t nbe(edges.size());
9333 std::vector<int> edges2(2*nbe); std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edgesPtr2(2*nbe);
9334 for(std::size_t i=0;i<nbe;i++)
9336 edges2[2*i]=edges[i]; edges2[2*i+1]=edges[(i+1)%nbe];
9337 edgesPtr2[2*i]=edgesPtr[(i+1)%nbe]; edgesPtr2[2*i+1]=edgesPtr[(i+1)%nbe];//tony a chier
9339 _edges.resize(4*nbe); _edges_ptr.resize(4*nbe);
9340 std::copy(edges2.begin(),edges2.end(),_edges.begin()); std::copy(edges2.begin(),edges2.end(),_edges.begin()+2*nbe);
9341 std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()); std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()+2*nbe);
9347 EdgeInfo(int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh):_istart(istart),_iend(iend),_mesh(mesh),_left(-7),_right(-7) { }
9348 EdgeInfo(int istart, int iend, int pos, const MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge>& edge):_istart(istart),_iend(iend),_edge(edge),_left(pos),_right(pos+1) { }
9349 bool isInMyRange(int pos) const { return pos>=_istart && pos<_iend; }
9350 void somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9351 void feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const;
9355 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _mesh;
9356 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> _edge;
9361 void EdgeInfo::somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9363 const MEDCouplingUMesh *mesh(_mesh);
9369 { _left++; _right++; return ; }
9372 bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9373 if((isLeft && isRight) || (!isLeft && !isRight))
9374 throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 1 !");
9385 bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9386 if((isLeft && isRight) || (!isLeft && !isRight))
9387 throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 2 !");
9402 void EdgeInfo::feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const
9404 const MEDCouplingUMesh *mesh(_mesh);
9407 neighbors[0]=offset+_left; neighbors[1]=offset+_right;
9410 {// not fully splitting cell case
9411 if(mesh2D->getNumberOfCells()==1)
9412 {//little optimization. 1 cell no need to find in which cell mesh is !
9413 neighbors[0]=offset; neighbors[1]=offset;
9418 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9419 int cellId(mesh2D->getCellContainingPoint(barys->begin(),eps));
9421 throw INTERP_KERNEL::Exception("EdgeInfo::feedEdgeInfoAt : internal error !");
9422 neighbors[0]=offset+cellId; neighbors[1]=offset+cellId;
9427 class VectorOfCellInfo
9430 VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9431 std::size_t size() const { return _pool.size(); }
9432 int getPositionOf(double eps, const MEDCouplingUMesh *mesh) const;
9433 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);
9434 const std::vector<int>& getConnOf(int pos) const { return get(pos)._edges; }
9435 const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& getEdgePtrOf(int pos) const { return get(pos)._edges_ptr; }
9436 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> getZeMesh() const { return _ze_mesh; }
9437 void feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const;
9439 int getZePosOfEdgeGivenItsGlobalId(int pos) const;
9440 void updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9441 const CellInfo& get(int pos) const;
9442 CellInfo& get(int pos);
9444 std::vector<CellInfo> _pool;
9445 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _ze_mesh;
9446 std::vector<EdgeInfo> _edge_info;
9449 VectorOfCellInfo::VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr):_pool(1)
9451 _pool[0]._edges=edges;
9452 _pool[0]._edges_ptr=edgesPtr;
9455 int VectorOfCellInfo::getPositionOf(double eps, const MEDCouplingUMesh *mesh) const
9458 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : empty !");
9461 const MEDCouplingUMesh *zeMesh(_ze_mesh);
9463 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : null aggregated mesh !");
9464 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9465 return zeMesh->getCellContainingPoint(barys->begin(),eps);
9468 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)
9470 get(pos);//to check pos
9471 bool isFast(pos==0 && _pool.size()==1);
9472 std::size_t sz(edges.size());
9473 // dealing with edges
9475 _edge_info.push_back(EdgeInfo(istart,iend,mesh1DInCase));
9477 _edge_info.push_back(EdgeInfo(istart,iend,pos,edgePtrs[0].back()));
9479 std::vector<CellInfo> pool(_pool.size()-1+sz);
9480 for(int i=0;i<pos;i++)
9482 for(std::size_t j=0;j<sz;j++)
9483 pool[pos+j]=CellInfo(edges[j],edgePtrs[j]);
9484 for(int i=pos+1;i<(int)_pool.size();i++)
9485 pool[i+sz-1]=_pool[i];
9489 updateEdgeInfo(pos,edgePtrs[0],edgePtrs[1]);
9497 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > ms;
9500 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(0,pos,true)));
9504 if(pos<_ze_mesh->getNumberOfCells()-1)
9506 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(pos+1,_ze_mesh->getNumberOfCells(),true)));
9509 std::vector< const MEDCouplingUMesh *> ms2(ms.size());
9510 for(std::size_t j=0;j<ms2.size();j++)
9512 _ze_mesh=MEDCouplingUMesh::MergeUMeshesOnSameCoords(ms2);
9515 void VectorOfCellInfo::feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const
9517 _edge_info[getZePosOfEdgeGivenItsGlobalId(pos)].feedEdgeInfoAt(eps,_ze_mesh,offset,neighbors);
9520 int VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId(int pos) const
9523 throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id ! Must be >=0 !");
9525 for(std::vector<EdgeInfo>::const_iterator it=_edge_info.begin();it!=_edge_info.end();it++,ret++)
9527 if((*it).isInMyRange(pos))
9530 throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id !");
9533 void VectorOfCellInfo::updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9535 get(pos);//to check;
9536 if(_edge_info.empty())
9538 std::size_t sz(_edge_info.size()-1);
9539 for(std::size_t i=0;i<sz;i++)
9540 _edge_info[i].somethingHappendAt(pos,newLeft,newRight);
9543 const CellInfo& VectorOfCellInfo::get(int pos) const
9545 if(pos<0 || pos>=(int)_pool.size())
9546 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get const : invalid pos !");
9550 CellInfo& VectorOfCellInfo::get(int pos)
9552 if(pos<0 || pos>=(int)_pool.size())
9553 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get : invalid pos !");
9559 * - a \b closed set of edges ( \a allEdges and \a allEdgesPtr ) that defines the split descending 2D cell.
9560 * - \a splitMesh1D a split 2D curve mesh contained into 2D cell defined above.
9562 * This method returns the 2D mesh and feeds \a idsLeftRight using offset.
9564 * Algorithm : \a splitMesh1D is cut into contiguous parts. Each contiguous parts will build incrementally the output 2D cells.
9566 * \param [in] allEdges a list of pairs (beginNode, endNode). Linked with \a allEdgesPtr to get the equation of edge.
9568 MEDCouplingUMesh *BuildMesh2DCutInternal(double eps, const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& allEdges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& allEdgesPtr, int offset,
9569 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9571 int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells());
9572 if(nbCellsInSplitMesh1D==0)
9573 throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal : internal error ! input 1D mesh must have at least one cell !");
9574 const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9575 std::size_t nb(allEdges.size()),jj;
9577 throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !");
9578 std::vector<int> edge1Bis(nb*2);
9579 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edge1BisPtr(nb*2);
9580 std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin());
9581 std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb);
9582 std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin());
9583 std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb);
9585 idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(nbCellsInSplitMesh1D*2); idsLeftRight->fillWithValue(-2); idsLeftRight->rearrange(2);
9586 int *idsLeftRightPtr(idsLeftRight->getPointer());
9587 VectorOfCellInfo pool(edge1Bis,edge1BisPtr);
9588 for(int iStart=0;iStart<nbCellsInSplitMesh1D;)
9589 {// split [0:nbCellsInSplitMesh1D) in contiguous parts [iStart:iEnd)
9591 for(;iEnd<nbCellsInSplitMesh1D;)
9593 for(jj=0;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd]+2];jj++);
9599 if(iEnd<nbCellsInSplitMesh1D)
9602 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfSplitMesh1D(static_cast<MEDCouplingUMesh *>(splitMesh1D->buildPartOfMySelf2(iStart,iEnd,1,true)));
9603 int pos(pool.getPositionOf(eps,partOfSplitMesh1D));
9605 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>retTmp(MEDCouplingUMesh::New("",2));
9606 retTmp->setCoords(splitMesh1D->getCoords());
9607 retTmp->allocateCells();
9609 std::vector< std::vector<int> > out0;
9610 std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > > out1;
9612 BuildMesh2DCutInternal2(partOfSplitMesh1D,pool.getConnOf(pos),pool.getEdgePtrOf(pos),out0,out1);
9613 for(std::size_t cnt=0;cnt<out0.size();cnt++)
9614 AddCellInMesh2D(retTmp,out0[cnt],out1[cnt]);
9615 pool.setMeshAt(pos,retTmp,iStart,iEnd,partOfSplitMesh1D,out0,out1);
9619 for(int mm=0;mm<nbCellsInSplitMesh1D;mm++)
9620 pool.feedEdgeInfoAt(eps,mm,offset,idsLeftRightPtr+2*mm);
9621 return pool.getZeMesh().retn();
9624 MEDCouplingUMesh *BuildMesh2DCutFrom(double eps, int cellIdInMesh2D, const MEDCouplingUMesh *mesh2DDesc, const MEDCouplingUMesh *splitMesh1D,
9625 const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1, int offset,
9626 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9628 const int *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin());
9630 std::vector<int> allEdges;
9631 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > allEdgesPtr; // for each sub edge in splitMesh2D the uncut Edge object of the original mesh2D
9632 for(const int *it(descBg);it!=descEnd;it++) // for all edges in the descending connectivity of the 2D mesh in relative Fortran mode
9634 int edgeId(std::abs(*it)-1);
9635 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9636 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m));
9637 const std::vector<int>& edge1(intersectEdge1[edgeId]);
9639 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9641 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9642 std::size_t sz(edge1.size());
9643 for(std::size_t cnt=0;cnt<sz;cnt++)
9644 allEdgesPtr.push_back(ee);
9647 return BuildMesh2DCutInternal(eps,splitMesh1D,allEdges,allEdgesPtr,offset,idsLeftRight);
9650 bool AreEdgeEqual(const double *coo2D, const INTERP_KERNEL::CellModel& typ1, const int *conn1, const INTERP_KERNEL::CellModel& typ2, const int *conn2, double eps)
9652 if(!typ1.isQuadratic() && !typ2.isQuadratic())
9653 {//easy case comparison not
9654 return conn1[0]==conn2[0] && conn1[1]==conn2[1];
9656 else if(typ1.isQuadratic() && typ2.isQuadratic())
9658 bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9661 if(conn1[2]==conn2[2])
9663 const double *a(coo2D+2*conn1[2]),*b(coo2D+2*conn2[2]);
9664 double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9668 {//only one is quadratic
9669 bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9672 const double *a(0),*bb(0),*be(0);
9673 if(typ1.isQuadratic())
9675 a=coo2D+2*conn1[2]; bb=coo2D+2*conn2[0]; be=coo2D+2*conn2[1];
9679 a=coo2D+2*conn2[2]; bb=coo2D+2*conn1[0]; be=coo2D+2*conn1[1];
9681 double b[2]; b[0]=(be[0]+bb[0])/2.; b[1]=(be[1]+bb[1])/2.;
9682 double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9688 * This method returns among the cellIds [ \a candidatesIn2DBg , \a candidatesIn2DEnd ) in \a mesh2DSplit those exactly sharing \a cellIdInMesh1DSplitRelative in \a mesh1DSplit.
9689 * \a mesh2DSplit and \a mesh1DSplit are expected to share the coordinates array.
9691 * \param [in] cellIdInMesh1DSplitRelative is in Fortran mode using sign to specify direction.
9693 int FindRightCandidateAmong(const MEDCouplingUMesh *mesh2DSplit, const int *candidatesIn2DBg, const int *candidatesIn2DEnd, const MEDCouplingUMesh *mesh1DSplit, int cellIdInMesh1DSplitRelative, double eps)
9695 if(candidatesIn2DEnd==candidatesIn2DBg)
9696 throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 1 !");
9697 const double *coo(mesh2DSplit->getCoords()->begin());
9698 if(std::distance(candidatesIn2DBg,candidatesIn2DEnd)==1)
9699 return *candidatesIn2DBg;
9700 int edgeId(std::abs(cellIdInMesh1DSplitRelative)-1);
9701 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur1D(static_cast<MEDCouplingUMesh *>(mesh1DSplit->buildPartOfMySelf(&edgeId,&edgeId+1,true)));
9702 if(cellIdInMesh1DSplitRelative<0)
9703 cur1D->changeOrientationOfCells();
9704 const int *c1D(cur1D->getNodalConnectivity()->begin());
9705 const INTERP_KERNEL::CellModel& ref1DType(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c1D[0]));
9706 for(const int *it=candidatesIn2DBg;it!=candidatesIn2DEnd;it++)
9708 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur2D(static_cast<MEDCouplingUMesh *>(mesh2DSplit->buildPartOfMySelf(it,it+1,true)));
9709 const int *c(cur2D->getNodalConnectivity()->begin()),*ci(cur2D->getNodalConnectivityIndex()->begin());
9710 const INTERP_KERNEL::CellModel &cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[0]]));
9711 unsigned sz(cm.getNumberOfSons2(c+ci[0]+1,ci[1]-ci[0]-1));
9712 INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[1]-ci[0]]);
9713 for(unsigned it2=0;it2<sz;it2++)
9715 INTERP_KERNEL::NormalizedCellType typeOfSon;
9716 cm.fillSonCellNodalConnectivity2(it2,c+ci[0]+1,ci[1]-ci[0]-1,tmpPtr,typeOfSon);
9717 const INTERP_KERNEL::CellModel &curCM(INTERP_KERNEL::CellModel::GetCellModel(typeOfSon));
9718 if(AreEdgeEqual(coo,ref1DType,c1D+1,curCM,tmpPtr,eps))
9722 throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 2 ! Unable to find the edge among split cell !");
9728 * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
9729 * 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
9730 * and finaly, in case of quadratic polygon the centers of edges new nodes.
9731 * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
9733 * \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
9734 * 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)
9735 * \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
9736 * you can invoke orderConsecutiveCells1D on \a mesh1D.
9737 * \param [in] eps - precision used to perform intersections and localization operations.
9738 * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
9739 * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
9740 * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
9741 * 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.
9742 * \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
9743 * and the cell in \a splitMesh2D on the right for the 2nt component. -1 means no cell.
9744 * 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.
9746 * \sa Intersect2DMeshes, orderConsecutiveCells1D, conformize2D, mergeNodes
9748 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
9750 if(!mesh2D || !mesh1D)
9751 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
9752 mesh2D->checkFullyDefined();
9753 mesh1D->checkFullyDefined();
9754 const std::vector<std::string>& compNames(mesh2D->getCoords()->getInfoOnComponents());
9755 if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
9756 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
9757 // Step 1: compute all edge intersections (new nodes)
9758 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9759 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
9760 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9761 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9763 // Build desc connectivity
9764 DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
9765 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9766 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
9767 std::map<int,int> mergedNodes;
9768 Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes);
9769 // use mergeNodes to fix intersectEdge1
9770 for(std::vector< std::vector<int> >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++)
9772 std::size_t n((*it0).size()/2);
9773 int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]);
9774 std::map<int,int>::const_iterator it1;
9775 it1=mergedNodes.find(eltStart);
9776 if(it1!=mergedNodes.end())
9777 (*it0)[0]=(*it1).second;
9778 it1=mergedNodes.find(eltEnd);
9779 if(it1!=mergedNodes.end())
9780 (*it0)[2*n-1]=(*it1).second;
9783 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9784 addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9785 // Step 2: re-order newly created nodes according to the ordering found in m2
9786 std::vector< std::vector<int> > intersectEdge2;
9787 BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
9789 // Step 3: compute splitMesh1D
9790 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear;
9791 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2(DataArrayInt::New()); ret2->alloc(0,1);
9792 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1,
9793 idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear));
9794 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(std::numeric_limits<int>::max()); ret3->rearrange(2);
9795 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells()));
9796 // deal with cells in mesh2D that are not cut but only some of their edges are
9797 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCpy());
9798 idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1);
9799 idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique();
9800 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
9801 if(!idsInDesc2DToBeRefined->empty())
9803 DataArrayInt *out0(0),*outi0(0);
9804 MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
9805 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> outi0s(outi0);
9807 out0s=out0s->buildUnique();
9811 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1NonCol(static_cast<MEDCouplingUMesh *>(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end())));
9812 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> baryRet1(ret1NonCol->getBarycenterAndOwner());
9813 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elts,eltsIndex;
9814 mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
9815 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex2(eltsIndex->deltaShiftIndex());
9816 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex3(eltsIndex2->getIdsEqual(1));
9817 if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells())
9818 throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !");
9819 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToBeModified(elts->buildUnique());
9820 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells()));
9821 if((DataArrayInt *)out0s)
9822 untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one
9823 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > outMesh2DSplit;
9824 // OK all is ready to insert in ret2 mesh
9825 if(!untouchedCells->empty())
9826 {// the most easy part, cells in mesh2D not impacted at all
9827 outMesh2DSplit.push_back(static_cast<MEDCouplingUMesh *>(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end())));
9828 outMesh2DSplit.back()->setCoords(ret1->getCoords());
9829 ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end());
9831 if((DataArrayInt *)out0s)
9832 {// here dealing with cells in out0s but not in cellsToBeModified
9833 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fewModifiedCells(out0s->buildSubstraction(cellsToBeModified));
9834 const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin());
9835 for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++)
9837 outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),mesh2D,*it,dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1));
9838 ret1->setCoords(outMesh2DSplit.back()->getCoords());
9840 int offset(ret2->getNumberOfTuples());
9841 ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end());
9842 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1);
9843 partOfRet3->fillWithValue(std::numeric_limits<int>::max()); partOfRet3->rearrange(2);
9844 int kk(0),*ret3ptr(partOfRet3->getPointer());
9845 for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++)
9847 int faceId(std::abs(*it)-1);
9848 for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++)
9850 int tmp(fewModifiedCells->locateValue(*it2));
9853 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9854 ret3ptr[2*kk]=tmp+offset;
9855 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9856 ret3ptr[2*kk+1]=tmp+offset;
9859 {//the current edge is shared by a 2D cell that will be split just after
9860 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9861 ret3ptr[2*kk]=-(*it2+1);
9862 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9863 ret3ptr[2*kk+1]=-(*it2+1);
9867 m1Desc->setCoords(ret1->getCoords());
9868 ret1NonCol->setCoords(ret1->getCoords());
9869 ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true);
9870 if(!outMesh2DSplit.empty())
9872 DataArrayDouble *da(outMesh2DSplit.back()->getCoords());
9873 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> >::iterator itt=outMesh2DSplit.begin();itt!=outMesh2DSplit.end();itt++)
9874 (*itt)->setCoords(da);
9877 cellsToBeModified=cellsToBeModified->buildUniqueNotSorted();
9878 for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++)
9880 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell(elts->getIdsEqual(*it));
9881 idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end());
9882 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end()));
9883 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfMesh1CuttingCur2DCell(static_cast<MEDCouplingUMesh *>(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end())));
9884 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3;
9885 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));
9886 ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true);
9887 outMesh2DSplit.push_back(splitOfOneCell);
9888 for(int i=0;i<splitOfOneCell->getNumberOfCells();i++)
9889 ret2->pushBackSilent(*it);
9892 std::size_t nbOfMeshes(outMesh2DSplit.size());
9893 std::vector<const MEDCouplingUMesh *> tmp(nbOfMeshes);
9894 for(std::size_t i=0;i<nbOfMeshes;i++)
9895 tmp[i]=outMesh2DSplit[i];
9897 ret1->getCoords()->setInfoOnComponents(compNames);
9898 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2D(MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp));
9899 // To finish - filter ret3 - std::numeric_limits<int>::max() -> -1 - negate values must be resolved.
9901 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> edgesToDealWith(ret3->getIdsStrictlyNegative());
9902 for(const int *it=edgesToDealWith->begin();it!=edgesToDealWith->end();it++)
9904 int old2DCellId(-ret3->getIJ(*it,0)-1);
9905 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates(ret2->getIdsEqual(old2DCellId));
9906 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
9908 ret3->replaceOneValByInThis(std::numeric_limits<int>::max(),-1);
9911 splitMesh1D=ret1.retn();
9912 splitMesh2D=ret2D.retn();
9913 cellIdInMesh2D=ret2.retn();
9914 cellIdInMesh1D=ret3.retn();
9918 * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
9919 * (newly created) nodes corresponding to the edge intersections.
9921 * @param[out] cr, crI connectivity of the resulting mesh
9922 * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
9923 * TODO: describe input parameters
9925 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
9926 const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
9927 const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
9928 const std::vector<double>& addCoords,
9929 std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
9931 static const int SPACEDIM=2;
9932 const double *coo1(m1->getCoords()->getConstPointer());
9933 const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer());
9934 int offset1(m1->getNumberOfNodes());
9935 const double *coo2(m2->getCoords()->getConstPointer());
9936 const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer());
9937 int offset2(offset1+m2->getNumberOfNodes());
9938 int offset3(offset2+((int)addCoords.size())/2);
9939 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
9940 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9941 // Here a BBTree on 2D-cells, not on segments:
9942 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
9943 int ncell1(m1->getNumberOfCells());
9945 for(int i=0;i<ncell1;i++)
9947 std::vector<int> candidates2;
9948 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9949 std::map<INTERP_KERNEL::Node *,int> mapp;
9950 std::map<int,INTERP_KERNEL::Node *> mappRev;
9951 INTERP_KERNEL::QuadraticPolygon pol1;
9952 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
9953 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
9954 // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
9955 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
9956 // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
9957 pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
9958 desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
9960 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
9961 std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
9962 INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
9963 for(it1.first();!it1.finished();it1.next())
9964 edges1.insert(it1.current()->getPtr());
9966 std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
9967 std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
9969 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9971 INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
9972 const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
9973 // Complete mapping with elements coming from the current cell it2 in mesh2:
9974 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
9975 // pol2 is the new QP in the final merged result.
9976 pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
9977 pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
9980 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9982 INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
9983 pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
9984 //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
9985 pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9987 // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
9988 // by m2 but that we still want to keep in the final result.
9993 INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9995 catch(INTERP_KERNEL::Exception& e)
9997 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();
9998 throw INTERP_KERNEL::Exception(oss.str().c_str());
10001 for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
10002 (*it).second->decrRef();
10007 * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
10008 * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
10009 * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
10010 * The caller is to deal with the resulting DataArrayInt.
10011 * \throw If the coordinate array is not set.
10012 * \throw If the nodal connectivity of the cells is not defined.
10013 * \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
10014 * \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
10016 * \sa DataArrayInt::sortEachPairToMakeALinkedList
10018 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
10020 checkFullyDefined();
10021 if(getMeshDimension()!=1)
10022 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
10024 // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
10025 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
10026 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
10027 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
10028 const int *d(_d->getConstPointer()), *dI(_dI->getConstPointer());
10029 const int *rD(_rD->getConstPointer()), *rDI(_rDI->getConstPointer());
10030 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
10031 const int * dsi(_dsi->getConstPointer());
10032 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dsii = _dsi->getIdsNotInRange(0,3);
10034 if (dsii->getNumberOfTuples())
10035 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
10037 int nc(getNumberOfCells());
10038 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> result(DataArrayInt::New());
10039 result->alloc(nc,1);
10041 // set of edges not used so far
10042 std::set<int> edgeSet;
10043 for (int i=0; i<nc; edgeSet.insert(i), i++);
10047 // while we have points with only one neighbor segments
10050 std::list<int> linePiece;
10051 // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
10052 for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
10054 // Fill the list forward (resp. backward) from the start segment:
10055 int activeSeg = startSeg;
10056 int prevPointId = -20;
10058 while (!edgeSet.empty())
10060 if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
10063 linePiece.push_back(activeSeg);
10065 linePiece.push_front(activeSeg);
10066 edgeSet.erase(activeSeg);
10069 int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
10070 ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
10071 if (dsi[ptId] == 1) // hitting the end of the line
10073 prevPointId = ptId;
10074 int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
10075 activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
10078 // Done, save final piece into DA:
10079 std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
10080 newIdx += linePiece.size();
10082 // identify next valid start segment (one which is not consumed)
10083 if(!edgeSet.empty())
10084 startSeg = *(edgeSet.begin());
10086 while (!edgeSet.empty());
10087 return result.retn();
10092 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10094 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> nTmp(n); nTmp->incrRef();
10095 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>::const_iterator it(m.find(nTmp));
10097 throw INTERP_KERNEL::Exception("Internal error in remapping !");
10098 int v((*it).second);
10099 if(v==forbVal0 || v==forbVal1)
10101 if(std::find(isect.begin(),isect.end(),v)==isect.end())
10102 isect.push_back(v);
10105 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10110 bool presenceOfOn(false);
10111 for(int i=0;i<sz;i++)
10113 INTERP_KERNEL::ElementaryEdge *e(c[i]);
10114 if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
10116 IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
10117 IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
10119 return presenceOfOn;
10125 * 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.
10126 * 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.
10127 * 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.
10128 * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to avoid to have a non conform mesh.
10130 * \return int - the number of new nodes created (in most of cases 0).
10132 * \throw If \a this is not coherent.
10133 * \throw If \a this has not spaceDim equal to 2.
10134 * \throw If \a this has not meshDim equal to 2.
10135 * \throw If some subcells needed to be split are orphan.
10136 * \sa MEDCouplingUMesh::conformize2D
10138 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
10140 if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
10141 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
10142 desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
10143 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10144 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10145 if(midOpt==0 && midOptI==0)
10147 split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
10150 else if(midOpt!=0 && midOptI!=0)
10151 return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
10153 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
10157 * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
10158 * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
10159 * 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
10160 * 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).
10161 * 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.
10163 * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
10164 * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
10166 * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
10167 * This method expects that all nodes in \a this are not closer than \a eps.
10168 * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
10170 * \param [in] eps the relative error to detect merged edges.
10171 * \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
10172 * that the user is expected to deal with.
10174 * \throw If \a this is not coherent.
10175 * \throw If \a this has not spaceDim equal to 2.
10176 * \throw If \a this has not meshDim equal to 2.
10177 * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
10179 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
10181 static const int SPACEDIM=2;
10183 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10184 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10185 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
10186 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
10187 const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
10188 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
10189 const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
10190 int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
10191 std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
10192 std::vector<double> addCoo;
10193 BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
10194 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10195 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10196 for(int i=0;i<nDescCell;i++)
10198 std::vector<int> candidates;
10199 myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
10200 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
10203 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10204 INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
10205 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
10206 INTERP_KERNEL::MergePoints merge;
10207 INTERP_KERNEL::QuadraticPolygon c1,c2;
10208 e1->intersectWith(e2,merge,c1,c2);
10209 e1->decrRef(); e2->decrRef();
10210 if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
10211 overlapEdge[i].push_back(*it);
10212 if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
10213 overlapEdge[*it].push_back(i);
10216 // splitting done. sort intersect point in intersectEdge.
10217 std::vector< std::vector<int> > middle(nDescCell);
10218 int nbOf2DCellsToBeSplit(0);
10219 bool middleNeedsToBeUsed(false);
10220 std::vector<bool> cells2DToTreat(nDescCell,false);
10221 for(int i=0;i<nDescCell;i++)
10223 std::vector<int>& isect(intersectEdge[i]);
10224 int sz((int)isect.size());
10227 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10228 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
10229 e->sortSubNodesAbs(coords,isect);
10234 int idx0(rdi[i]),idx1(rdi[i+1]);
10236 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
10237 if(!cells2DToTreat[rd[idx0]])
10239 cells2DToTreat[rd[idx0]]=true;
10240 nbOf2DCellsToBeSplit++;
10242 // try to reuse at most eventual 'middle' of SEG3
10243 std::vector<int>& mid(middle[i]);
10244 mid.resize(sz+1,-1);
10245 if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
10247 middleNeedsToBeUsed=true;
10248 const std::vector<int>& candidates(overlapEdge[i]);
10249 std::vector<int> trueCandidates;
10250 for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
10251 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
10252 trueCandidates.push_back(*itc);
10253 int stNode(c[ci[i]+1]),endNode(isect[0]);
10254 for(int j=0;j<sz+1;j++)
10256 for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
10258 int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
10259 if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
10260 { mid[j]=*itc; break; }
10263 endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
10268 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
10269 if(nbOf2DCellsToBeSplit==0)
10272 int *retPtr(ret->getPointer());
10273 for(int i=0;i<nCell;i++)
10274 if(cells2DToTreat[i])
10277 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
10278 DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
10279 MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
10280 DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
10281 if(middleNeedsToBeUsed)
10282 { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
10283 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
10284 int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
10285 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.
10286 setPartOfMySelf(ret->begin(),ret->end(),*modif);
10288 bool areNodesMerged; int newNbOfNodes;
10289 if(nbOfNodesCreated!=0)
10290 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
10296 * 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.
10297 * 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).
10298 * 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
10299 * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
10300 * 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
10301 * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
10303 * 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
10304 * using new instance, idem for coordinates.
10306 * 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.
10308 * \return DataArrayInt * - The list of cellIds in \a this that have at least one edge colinearized.
10310 * \throw If \a this is not coherent.
10311 * \throw If \a this has not spaceDim equal to 2.
10312 * \throw If \a this has not meshDim equal to 2.
10314 * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
10316 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
10318 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
10320 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10321 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10322 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10323 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10324 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
10325 const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
10326 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
10327 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
10328 const double *coords(_coords->begin());
10329 int *newciptr(newci->getPointer());
10330 for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
10332 if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
10333 ret->pushBackSilent(i);
10334 newciptr[1]=newc->getNumberOfTuples();
10339 if(!appendedCoords->empty())
10341 appendedCoords->rearrange(2);
10342 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
10344 setCoords(newCoords);
10347 setConnectivity(newc,newci,true);
10352 * \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.
10353 * 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.
10354 * And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
10355 * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
10356 * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
10357 * \param [out] addCoo - nodes to be append at the end
10358 * \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.
10360 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
10361 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)
10363 static const int SPACEDIM=2;
10364 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10365 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10366 const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer());
10367 // Build BB tree of all edges in the tool mesh (second mesh)
10368 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
10369 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10370 int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
10371 intersectEdge1.resize(nDescCell1);
10372 colinear2.resize(nDescCell2);
10373 subDiv2.resize(nDescCell2);
10374 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
10376 std::vector<int> candidates1(1);
10377 int offset1(m1Desc->getNumberOfNodes());
10378 int offset2(offset1+m2Desc->getNumberOfNodes());
10379 for(int i=0;i<nDescCell1;i++) // for all edges in the first mesh
10381 std::vector<int> candidates2; // edges of mesh2 candidate for intersection
10382 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10383 if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
10385 std::map<INTERP_KERNEL::Node *,int> map1,map2;
10386 // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
10387 INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
10389 INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
10390 // 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
10391 // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
10392 std::set<INTERP_KERNEL::Node *> nodes;
10393 pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
10394 std::size_t szz(nodes.size());
10395 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
10396 std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
10397 for(std::size_t iii=0;iii<szz;iii++,itt++)
10398 { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
10399 // end of protection
10400 // Performs egde cutting:
10401 pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes);
10406 // Copy the edge (take only the two first points, ie discard quadratic point at this stage)
10407 intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i]+3);
10412 * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
10413 * It builds the descending connectivity of the two meshes, and then using a binary tree
10414 * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
10415 * Documentation about parameters colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
10417 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
10418 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
10419 MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
10420 std::vector<double>& addCoo,
10421 MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
10423 // Build desc connectivity
10424 desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
10425 desc2=DataArrayInt::New();
10426 descIndx2=DataArrayInt::New();
10427 revDesc2=DataArrayInt::New();
10428 revDescIndx2=DataArrayInt::New();
10429 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
10430 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
10431 m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
10432 m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
10433 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
10434 std::map<int,int> notUsedMap;
10435 Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap);
10436 m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
10437 m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
10441 * This method performs the 2nd step of Partition of 2D mesh.
10442 * This method has 4 inputs :
10443 * - a mesh 'm1' with meshDim==1 and a SpaceDim==2
10444 * - a mesh 'm2' with meshDim==1 and a SpaceDim==2
10445 * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
10446 * 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'
10447 * Nodes end up lying consecutively on a cutted edge.
10448 * \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.
10449 * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
10450 * \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.
10451 * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
10452 * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
10454 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
10455 const std::vector<double>& addCoo,
10456 const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
10458 int offset1=m1->getNumberOfNodes();
10459 int ncell=m2->getNumberOfCells();
10460 const int *c=m2->getNodalConnectivity()->getConstPointer();
10461 const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
10462 const double *coo=m2->getCoords()->getConstPointer();
10463 const double *cooBis=m1->getCoords()->getConstPointer();
10464 int offset2=offset1+m2->getNumberOfNodes();
10465 intersectEdge.resize(ncell);
10466 for(int i=0;i<ncell;i++,cI++)
10468 const std::vector<int>& divs=subDiv[i];
10469 int nnode=cI[1]-cI[0]-1;
10470 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
10471 std::map<INTERP_KERNEL::Node *, int> mapp22;
10472 for(int j=0;j<nnode;j++)
10474 INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
10475 int nnid=c[(*cI)+j+1];
10476 mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
10477 mapp22[nn]=nnid+offset1;
10479 INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
10480 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
10481 ((*it).second.first)->decrRef();
10482 std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
10483 std::map<INTERP_KERNEL::Node *,int> mapp3;
10484 for(std::size_t j=0;j<divs.size();j++)
10487 INTERP_KERNEL::Node *tmp=0;
10489 tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
10490 else if(id<offset2)
10491 tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
10493 tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
10497 e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
10498 for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
10505 * 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).
10506 * 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
10507 * with a plane. The result will be put in 'cut3DSuf' out parameter.
10508 * \param [in] cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
10509 * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
10510 * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
10511 * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
10512 * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
10513 * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
10514 * \param [in] desc is the descending connectivity 3DSurf->3DCurve
10515 * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
10516 * \param [out] cut3DSuf input/output param.
10518 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
10519 const int *nodal3DCurve, const int *nodalIndx3DCurve,
10520 const int *desc, const int *descIndx,
10521 std::vector< std::pair<int,int> >& cut3DSurf)
10523 std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
10524 int nbOf3DSurfCell=(int)cut3DSurf.size();
10525 for(int i=0;i<nbOf3DSurfCell;i++)
10527 std::vector<int> res;
10528 int offset=descIndx[i];
10529 int nbOfSeg=descIndx[i+1]-offset;
10530 for(int j=0;j<nbOfSeg;j++)
10532 int edgeId=desc[offset+j];
10533 int status=cut3DCurve[edgeId];
10537 res.push_back(status);
10540 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
10541 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
10549 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10555 std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
10556 std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
10559 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10563 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
10568 {// case when plane is on a multi colinear edge of a polyhedron
10569 if((int)res.size()==2*nbOfSeg)
10571 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
10574 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
10581 * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
10582 * 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).
10583 * 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
10584 * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
10585 * \param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
10586 * \param desc is the descending connectivity 3D->3DSurf
10587 * \param descIndx is the descending connectivity index 3D->3DSurf
10589 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
10590 const int *desc, const int *descIndx,
10591 DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
10593 checkFullyDefined();
10594 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10595 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
10596 const int *nodal3D=_nodal_connec->getConstPointer();
10597 const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
10598 int nbOfCells=getNumberOfCells();
10599 for(int i=0;i<nbOfCells;i++)
10601 std::map<int, std::set<int> > m;
10602 int offset=descIndx[i];
10603 int nbOfFaces=descIndx[i+1]-offset;
10606 for(int j=0;j<nbOfFaces;j++)
10608 const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
10609 if(p.first!=-1 && p.second!=-1)
10613 start=p.first; end=p.second;
10614 m[p.first].insert(p.second);
10615 m[p.second].insert(p.first);
10619 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
10620 int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
10621 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
10622 INTERP_KERNEL::NormalizedCellType cmsId;
10623 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
10624 start=tmp[0]; end=tmp[nbOfNodesSon-1];
10625 for(unsigned k=0;k<nbOfNodesSon;k++)
10627 m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
10628 m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
10635 std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
10639 std::map<int, std::set<int> >::const_iterator it=m.find(start);
10640 const std::set<int>& s=(*it).second;
10641 std::set<int> s2; s2.insert(prev);
10643 std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
10646 int val=*s3.begin();
10647 conn.push_back(start);
10654 conn.push_back(end);
10657 nodalRes->insertAtTheEnd(conn.begin(),conn.end());
10658 nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
10659 cellIds->pushBackSilent(i);
10665 * 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
10666 * 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
10667 * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
10668 * 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
10669 * 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.
10671 * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
10673 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
10675 std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
10678 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
10679 if(cm.getDimension()==2)
10681 const int *node=nodalConnBg+1;
10682 int startNode=*node++;
10683 double refX=coords[2*startNode];
10684 for(;node!=nodalConnEnd;node++)
10686 if(coords[2*(*node)]<refX)
10689 refX=coords[2*startNode];
10692 std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
10696 double angle0=-M_PI/2;
10701 double angleNext=0.;
10702 while(nextNode!=startNode)
10706 for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
10708 if(*node!=tmpOut.back() && *node!=prevNode)
10710 tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
10711 double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
10716 res=angle0-angleM+2.*M_PI;
10725 if(nextNode!=startNode)
10727 angle0=angleNext-M_PI;
10730 prevNode=tmpOut.back();
10731 tmpOut.push_back(nextNode);
10734 std::vector<int> tmp3(2*(sz-1));
10735 std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
10736 std::copy(nodalConnBg+1,nodalConnEnd,it);
10737 if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
10739 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10742 if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
10744 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10749 nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
10750 nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
10755 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10758 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10762 * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
10763 * 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.
10765 * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
10766 * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
10767 * \param [in,out] arr array in which the remove operation will be done.
10768 * \param [in,out] arrIndx array in the remove operation will modify
10769 * \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])
10770 * \return true if \b arr and \b arrIndx have been modified, false if not.
10772 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
10774 if(!arrIndx || !arr)
10775 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
10776 if(offsetForRemoval<0)
10777 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
10778 std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
10779 int nbOfGrps=arrIndx->getNumberOfTuples()-1;
10780 int *arrIPtr=arrIndx->getPointer();
10782 int previousArrI=0;
10783 const int *arrPtr=arr->getConstPointer();
10784 std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
10785 for(int i=0;i<nbOfGrps;i++,arrIPtr++)
10787 if(*arrIPtr-previousArrI>offsetForRemoval)
10789 for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
10791 if(s.find(*work)==s.end())
10792 arrOut.push_back(*work);
10795 previousArrI=*arrIPtr;
10796 *arrIPtr=(int)arrOut.size();
10798 if(arr->getNumberOfTuples()==(int)arrOut.size())
10800 arr->alloc((int)arrOut.size(),1);
10801 std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
10806 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10807 * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
10808 * The selection of extraction is done standardly in new2old format.
10809 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10811 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10812 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10813 * \param [in] arrIn arr origin array from which the extraction will be done.
10814 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10815 * \param [out] arrOut the resulting array
10816 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10817 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
10819 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10820 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10822 if(!arrIn || !arrIndxIn)
10823 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
10824 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10825 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10826 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
10827 std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
10828 const int *arrInPtr=arrIn->getConstPointer();
10829 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10830 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10832 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10833 int maxSizeOfArr=arrIn->getNumberOfTuples();
10834 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10835 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10836 arrIo->alloc((int)(sz+1),1);
10837 const int *idsIt=idsOfSelectBg;
10838 int *work=arrIo->getPointer();
10841 for(std::size_t i=0;i<sz;i++,work++,idsIt++)
10843 if(*idsIt>=0 && *idsIt<nbOfGrps)
10844 lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
10847 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10848 throw INTERP_KERNEL::Exception(oss.str().c_str());
10854 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
10855 oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
10856 throw INTERP_KERNEL::Exception(oss.str().c_str());
10859 arro->alloc(lgth,1);
10860 work=arro->getPointer();
10861 idsIt=idsOfSelectBg;
10862 for(std::size_t i=0;i<sz;i++,idsIt++)
10864 if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
10865 work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
10868 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
10869 oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10870 throw INTERP_KERNEL::Exception(oss.str().c_str());
10873 arrOut=arro.retn();
10874 arrIndexOut=arrIo.retn();
10878 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10879 * 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 ).
10880 * The selection of extraction is done standardly in new2old format.
10881 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10883 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10884 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10885 * \param [in] arrIn arr origin array from which the extraction will be done.
10886 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10887 * \param [out] arrOut the resulting array
10888 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10889 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
10891 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10892 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10894 if(!arrIn || !arrIndxIn)
10895 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
10896 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10897 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10898 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
10899 int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
10900 const int *arrInPtr=arrIn->getConstPointer();
10901 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10902 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10904 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10905 int maxSizeOfArr=arrIn->getNumberOfTuples();
10906 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10907 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10908 arrIo->alloc((int)(sz+1),1);
10909 int idsIt=idsOfSelectStart;
10910 int *work=arrIo->getPointer();
10913 for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
10915 if(idsIt>=0 && idsIt<nbOfGrps)
10916 lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
10919 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10920 throw INTERP_KERNEL::Exception(oss.str().c_str());
10926 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
10927 oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
10928 throw INTERP_KERNEL::Exception(oss.str().c_str());
10931 arro->alloc(lgth,1);
10932 work=arro->getPointer();
10933 idsIt=idsOfSelectStart;
10934 for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
10936 if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
10937 work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
10940 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
10941 oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10942 throw INTERP_KERNEL::Exception(oss.str().c_str());
10945 arrOut=arro.retn();
10946 arrIndexOut=arrIo.retn();
10950 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10951 * 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
10952 * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
10953 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
10955 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10956 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10957 * \param [in] arrIn arr origin array from which the extraction will be done.
10958 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10959 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
10960 * \param [in] srcArrIndex index array of \b srcArr
10961 * \param [out] arrOut the resulting array
10962 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10964 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
10966 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10967 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
10968 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10970 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10971 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
10972 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10973 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10974 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10975 std::vector<bool> v(nbOfTuples,true);
10977 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10978 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10979 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10981 if(*it>=0 && *it<nbOfTuples)
10984 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
10988 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
10989 throw INTERP_KERNEL::Exception(oss.str().c_str());
10992 srcArrIndexPtr=srcArrIndex->getConstPointer();
10993 arrIo->alloc(nbOfTuples+1,1);
10994 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
10995 const int *arrInPtr=arrIn->getConstPointer();
10996 const int *srcArrPtr=srcArr->getConstPointer();
10997 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
10998 int *arroPtr=arro->getPointer();
10999 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11003 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11004 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11008 std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
11009 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11010 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11013 arrOut=arro.retn();
11014 arrIndexOut=arrIo.retn();
11018 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11019 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11021 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
11022 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
11023 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11024 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11025 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
11026 * \param [in] srcArrIndex index array of \b srcArr
11028 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
11030 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11031 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11033 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11034 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
11035 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11036 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11037 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11038 int *arrInOutPtr=arrInOut->getPointer();
11039 const int *srcArrPtr=srcArr->getConstPointer();
11040 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
11042 if(*it>=0 && *it<nbOfTuples)
11044 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
11045 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
11048 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] !";
11049 throw INTERP_KERNEL::Exception(oss.str().c_str());
11054 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
11055 throw INTERP_KERNEL::Exception(oss.str().c_str());
11061 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11062 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11063 * 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]].
11064 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11065 * A negative value in \b arrIn means that it is ignored.
11066 * 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.
11068 * \param [in] arrIn arr origin array from which the extraction will be done.
11069 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11070 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11071 * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
11073 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
11075 int seed=0,nbOfDepthPeelingPerformed=0;
11076 return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
11080 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11081 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11082 * 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]].
11083 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11084 * A negative value in \b arrIn means that it is ignored.
11085 * 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.
11086 * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
11087 * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
11088 * \param [in] arrIn arr origin array from which the extraction will be done.
11089 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11090 * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
11091 * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
11092 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11093 * \sa MEDCouplingUMesh::partitionBySpreadZone
11095 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11097 nbOfDepthPeelingPerformed=0;
11099 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
11100 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11103 DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
11107 std::vector<bool> fetched(nbOfTuples,false);
11108 return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
11111 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11113 nbOfDepthPeelingPerformed=0;
11114 if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
11115 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
11116 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11117 std::vector<bool> fetched2(nbOfTuples,false);
11119 for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
11121 if(*seedElt>=0 && *seedElt<nbOfTuples)
11122 { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
11124 { 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()); }
11126 const int *arrInPtr=arrIn->getConstPointer();
11127 const int *arrIndxPtr=arrIndxIn->getConstPointer();
11128 int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
11129 std::vector<int> idsToFetch1(seedBg,seedEnd);
11130 std::vector<int> idsToFetch2;
11131 std::vector<int> *idsToFetch=&idsToFetch1;
11132 std::vector<int> *idsToFetchOther=&idsToFetch2;
11133 while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
11135 for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
11136 for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
11138 { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
11139 std::swap(idsToFetch,idsToFetchOther);
11140 idsToFetchOther->clear();
11141 nbOfDepthPeelingPerformed++;
11143 int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
11145 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
11146 int *retPtr=ret->getPointer();
11147 for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
11154 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11155 * 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
11156 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11157 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11159 * \param [in] start begin of set of ids of the input extraction (included)
11160 * \param [in] end end of set of ids of the input extraction (excluded)
11161 * \param [in] step step of the set of ids in range mode.
11162 * \param [in] arrIn arr origin array from which the extraction will be done.
11163 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11164 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11165 * \param [in] srcArrIndex index array of \b srcArr
11166 * \param [out] arrOut the resulting array
11167 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11169 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
11171 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11172 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11173 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11175 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11176 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
11177 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
11178 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
11179 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11181 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11182 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11183 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
11185 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11187 if(it>=0 && it<nbOfTuples)
11188 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
11191 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11192 throw INTERP_KERNEL::Exception(oss.str().c_str());
11195 srcArrIndexPtr=srcArrIndex->getConstPointer();
11196 arrIo->alloc(nbOfTuples+1,1);
11197 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11198 const int *arrInPtr=arrIn->getConstPointer();
11199 const int *srcArrPtr=srcArr->getConstPointer();
11200 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11201 int *arroPtr=arro->getPointer();
11202 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11204 int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
11207 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11208 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11212 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11213 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11216 arrOut=arro.retn();
11217 arrIndexOut=arrIo.retn();
11221 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11222 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11224 * \param [in] start begin of set of ids of the input extraction (included)
11225 * \param [in] end end of set of ids of the input extraction (excluded)
11226 * \param [in] step step of the set of ids in range mode.
11227 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11228 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11229 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11230 * \param [in] srcArrIndex index array of \b srcArr
11232 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11234 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11235 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11237 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11238 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
11239 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11240 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11241 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11242 int *arrInOutPtr=arrInOut->getPointer();
11243 const int *srcArrPtr=srcArr->getConstPointer();
11244 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
11246 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11248 if(it>=0 && it<nbOfTuples)
11250 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
11251 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
11254 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
11255 throw INTERP_KERNEL::Exception(oss.str().c_str());
11260 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11261 throw INTERP_KERNEL::Exception(oss.str().c_str());
11267 * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
11268 * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
11269 * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
11270 * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
11271 * The sum of measure field of returned mesh is equal to the sum of measure field of this.
11273 * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
11275 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
11277 checkFullyDefined();
11278 int mdim=getMeshDimension();
11279 int spaceDim=getSpaceDimension();
11281 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
11282 std::vector<DataArrayInt *> partition=partitionBySpreadZone();
11283 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
11284 std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
11285 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
11286 ret->setCoords(getCoords());
11287 ret->allocateCells((int)partition.size());
11289 for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
11291 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
11292 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
11296 cell=tmp->buildUnionOf2DMesh();
11299 cell=tmp->buildUnionOf3DMesh();
11302 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
11305 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
11308 ret->finishInsertingCells();
11313 * This method partitions \b this into contiguous zone.
11314 * This method only needs a well defined connectivity. Coordinates are not considered here.
11315 * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
11317 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
11319 int nbOfCellsCur=getNumberOfCells();
11320 std::vector<DataArrayInt *> ret;
11321 if(nbOfCellsCur<=0)
11323 DataArrayInt *neigh=0,*neighI=0;
11324 computeNeighborsOfCells(neigh,neighI);
11325 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
11326 std::vector<bool> fetchedCells(nbOfCellsCur,false);
11327 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
11329 while(seed<nbOfCellsCur)
11331 int nbOfPeelPerformed=0;
11332 ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
11333 seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
11335 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
11336 ret.push_back((*it).retn());
11341 * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
11342 * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
11344 * \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.
11345 * \return a newly allocated DataArrayInt to be managed by the caller.
11346 * \throw In case of \a code has not the right format (typically of size 3*n)
11348 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
11350 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
11351 std::size_t nb=code.size()/3;
11352 if(code.size()%3!=0)
11353 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
11354 ret->alloc((int)nb,2);
11355 int *retPtr=ret->getPointer();
11356 for(std::size_t i=0;i<nb;i++,retPtr+=2)
11358 retPtr[0]=code[3*i+2];
11359 retPtr[1]=code[3*i+2]+code[3*i+1];
11365 * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
11366 * All cells in \a this are expected to be linear 3D cells.
11367 * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
11368 * It leads to an increase to number of cells.
11369 * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
11370 * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints
11371 * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
11373 * \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.
11374 * For all other cells, the splitting policy will be ignored. See INTERP_KERNEL::SplittingPolicy for the images.
11375 * \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.
11376 * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
11377 * an id of old cell producing it. The caller is to delete this array using
11378 * decrRef() as it is no more needed.
11379 * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
11381 * \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
11382 * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
11384 * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
11385 * \throw If \a this is not fully constituted with linear 3D cells.
11386 * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
11388 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
11390 INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
11391 checkConnectivityFullyDefined();
11392 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
11393 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
11394 int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
11395 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
11396 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
11397 int *retPt(ret->getPointer());
11398 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
11399 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
11400 const int *oldc(_nodal_connec->begin());
11401 const int *oldci(_nodal_connec_index->begin());
11402 const double *coords(_coords->begin());
11403 for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
11405 std::vector<int> a; std::vector<double> b;
11406 INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
11407 std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
11408 const int *aa(&a[0]);
11411 for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
11413 *it=(-(*(it))-1+nbNodes);
11414 addPts->insertAtTheEnd(b.begin(),b.end());
11415 nbNodes+=(int)b.size()/3;
11417 for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
11418 newConn->insertAtTheEnd(aa,aa+4);
11420 if(!addPts->empty())
11422 addPts->rearrange(3);
11423 nbOfAdditionalPoints=addPts->getNumberOfTuples();
11424 addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
11425 ret0->setCoords(addPts);
11429 nbOfAdditionalPoints=0;
11430 ret0->setCoords(getCoords());
11432 ret0->setNodalConnectivity(newConn);
11434 ret->computeOffsets2();
11435 n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
11436 return ret0.retn();
11440 * 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).
11442 * \sa MEDCouplingUMesh::split2DCells
11444 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
11446 checkConnectivityFullyDefined();
11447 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
11448 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11449 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11450 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11451 int prevPosOfCi(ciPtr[0]);
11452 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11454 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
11455 *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
11456 for(int j=0;j<sz;j++)
11458 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
11459 for(int k=0;k<sz2;k++)
11460 *cPtr++=subPtr[offset2+k];
11462 *cPtr++=oldConn[prevPosOfCi+j+2];
11465 prevPosOfCi=ciPtr[1];
11466 ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11469 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
11470 _nodal_connec->decrRef();
11471 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
11474 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11480 int ret(nodesCnter++);
11482 e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
11483 addCoo.insertAtTheEnd(newPt,newPt+2);
11488 int InternalAddPointOriented(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11494 int ret(nodesCnter++);
11496 e->getMiddleOfPointsOriented(coo+2*startId,coo+2*endId,newPt);
11497 addCoo.insertAtTheEnd(newPt,newPt+2);
11505 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)
11508 int trueStart(start>=0?start:nbOfEdges+start);
11509 tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
11510 newConnOfCell->insertAtTheEnd(tmp,tmp+3);
11515 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11516 InternalAddPointOriented(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
11517 middles.push_back(tmp3+offset);
11520 middles.push_back(connBg[trueStart+nbOfEdges]);
11524 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)
11526 int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
11527 newConnOfCell->pushBackSilent(tmpEnd);
11532 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11533 InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11534 middles.push_back(tmp3+offset);
11537 middles.push_back(connBg[start+nbOfEdges]);
11541 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)
11543 // only the quadratic point to deal with:
11548 int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
11549 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11550 InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11551 middles.push_back(tmp3+offset);
11554 middles.push_back(connBg[start+nbOfEdges]);
11561 * 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 ) .
11562 * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
11564 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
11566 std::size_t sz(std::distance(connBg,connEnd));
11567 if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
11568 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
11570 INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
11571 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
11572 unsigned nbs(cm.getNumberOfSons2(connBg+1,sz));
11573 unsigned nbOfHit(0); // number of fusions operated
11574 int posBaseElt(0),posEndElt(0),nbOfTurn(0);
11575 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
11576 INTERP_KERNEL::NormalizedCellType typeOfSon;
11577 std::vector<int> middles;
11579 for(;(nbOfTurn+nbOfHit)<nbs;nbOfTurn++)
11581 cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
11582 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
11583 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11584 posEndElt = posBaseElt+1;
11586 // Look backward first: are the final edges of the cells colinear with the first ones?
11587 // This initializes posBaseElt.
11590 for(unsigned i=1;i<nbs && nbOfHit<maxNbOfHit;i++) // 2nd condition is to avoid ending with a cell wih one single edge
11592 cm.fillSonCellNodalConnectivity2(nbs-i,connBg+1,sz,tmpConn,typeOfSon);
11593 INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11594 INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11595 bool isColinear=eint->areColinears();
11608 // Now move forward:
11609 const unsigned fwdStart = (nbOfTurn == 0 ? 0 : posBaseElt); // the first element to be inspected going forward
11610 for(unsigned j=fwdStart+1;j<nbs && nbOfHit<maxNbOfHit;j++) // 2nd condition is to avoid ending with a cell wih one single edge
11612 cm.fillSonCellNodalConnectivity2((int)j,connBg+1,sz,tmpConn,typeOfSon); // get edge #j's connectivity
11613 INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11614 INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11615 bool isColinear(eint->areColinears());
11627 //push [posBaseElt,posEndElt) in newConnOfCell using e
11628 // 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!
11630 // at the begining of the connectivity (insert type)
11631 EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11632 else if((nbOfHit+nbOfTurn) != (nbs-1))
11634 EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11635 if ((nbOfHit+nbOfTurn) == (nbs-1))
11636 // at the end (only quad points to deal with)
11637 EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11638 posBaseElt=posEndElt;
11641 if(!middles.empty())
11642 newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
11647 * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
11649 * \return int - the number of new nodes created.
11650 * \sa MEDCouplingUMesh::split2DCells
11652 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
11655 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
11656 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11657 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
11658 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11659 const int *midPtr(mid->begin()),*midIPtr(midI->begin());
11660 const double *oldCoordsPtr(getCoords()->begin());
11661 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11662 int prevPosOfCi(ciPtr[0]);
11663 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11665 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
11666 for(int j=0;j<sz;j++)
11667 { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
11668 *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
11669 for(int j=0;j<sz;j++)//loop over subedges of oldConn
11671 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
11675 cPtr[1]=oldConn[prevPosOfCi+2+j];
11676 cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
11679 std::vector<INTERP_KERNEL::Node *> ns(3);
11680 ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
11681 ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
11682 ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
11683 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
11684 for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
11686 cPtr[1]=subPtr[offset2+k];
11687 cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
11689 int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
11691 { cPtr[1]=tmpEnd; }
11692 cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
11694 prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
11695 ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11698 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
11699 _nodal_connec->decrRef();
11700 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
11701 addCoo->rearrange(2);
11702 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
11704 return addCoo->getNumberOfTuples();
11707 void MEDCouplingUMesh::ComputeAllTypesInternal(std::set<INTERP_KERNEL::NormalizedCellType>& types, const DataArrayInt *nodalConnec, const DataArrayInt *nodalConnecIndex)
11709 if(nodalConnec && nodalConnecIndex)
11712 const int *conn(nodalConnec->getConstPointer()),*connIndex(nodalConnecIndex->getConstPointer());
11713 int nbOfElem(nodalConnecIndex->getNbOfElems()-1);
11715 for(const int *pt=connIndex;pt!=connIndex+nbOfElem;pt++)
11716 types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
11720 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
11721 _own_cell(true),_cell_id(-1),_nb_cell(0)
11726 _nb_cell=mesh->getNumberOfCells();
11730 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
11738 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
11739 _own_cell(false),_cell_id(bg-1),
11746 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
11749 if(_cell_id<_nb_cell)
11758 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
11764 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
11766 return new MEDCouplingUMeshCellByTypeIterator(_mesh);
11769 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
11775 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
11783 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
11789 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
11794 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
11799 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
11801 return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
11804 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
11809 _nb_cell=mesh->getNumberOfCells();
11813 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
11820 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
11822 const int *c=_mesh->getNodalConnectivity()->getConstPointer();
11823 const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
11824 if(_cell_id<_nb_cell)
11826 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
11827 int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
11828 int startId=_cell_id;
11829 _cell_id+=nbOfElems;
11830 return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
11836 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
11840 _conn=mesh->getNodalConnectivity()->getPointer();
11841 _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
11845 void MEDCouplingUMeshCell::next()
11847 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11852 _conn_lgth=_conn_indx[1]-_conn_indx[0];
11855 std::string MEDCouplingUMeshCell::repr() const
11857 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11859 std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
11861 std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
11865 return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
11868 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
11870 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11871 return (INTERP_KERNEL::NormalizedCellType)_conn[0];
11873 return INTERP_KERNEL::NORM_ERROR;
11876 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
11879 if(_conn_lgth!=NOTICABLE_FIRST_VAL)