1 // Copyright (C) 2007-2014 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 "CellModel.hxx"
26 #include "VolSurfUser.txx"
27 #include "InterpolationUtils.hxx"
28 #include "PointLocatorAlgos.txx"
30 #include "BBTreeDst.txx"
31 #include "SplitterTetra.hxx"
32 #include "DirectedBoundingBox.hxx"
33 #include "InterpKernelMatrixTools.hxx"
34 #include "InterpKernelMeshQuality.hxx"
35 #include "InterpKernelCellSimplify.hxx"
36 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
37 #include "InterpKernelAutoPtr.hxx"
38 #include "InterpKernelGeo2DNode.hxx"
39 #include "InterpKernelGeo2DEdgeLin.hxx"
40 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
41 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
50 using namespace ParaMEDMEM;
52 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
54 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 };
56 MEDCouplingUMesh *MEDCouplingUMesh::New()
58 return new MEDCouplingUMesh;
61 MEDCouplingUMesh *MEDCouplingUMesh::New(const std::string& meshName, int meshDim)
63 MEDCouplingUMesh *ret=new MEDCouplingUMesh;
64 ret->setName(meshName);
65 ret->setMeshDimension(meshDim);
70 * Returns a new MEDCouplingMesh which is a full copy of \a this one. No data is shared
71 * between \a this and the new mesh.
72 * \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
73 * delete this mesh using decrRef() as it is no more needed.
75 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
81 * Returns a new MEDCouplingMesh which is a copy of \a this one.
82 * \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
83 * this mesh are shared by the new mesh.
84 * \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
85 * delete this mesh using decrRef() as it is no more needed.
87 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
89 return new MEDCouplingUMesh(*this,recDeepCpy);
93 * This method behaves mostly like MEDCouplingUMesh::deepCpy method, except that only nodal connectivity arrays are deeply copied.
94 * The coordinates are shared between \a this and the returned instance.
96 * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
97 * \sa MEDCouplingUMesh::deepCpy
99 MEDCouplingPointSet *MEDCouplingUMesh::deepCpyConnectivityOnly() const
101 checkConnectivityFullyDefined();
102 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=clone(false);
103 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(getNodalConnectivity()->deepCpy()),ci(getNodalConnectivityIndex()->deepCpy());
104 ret->setConnectivity(c,ci);
108 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other)
111 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
112 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
114 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
115 MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
116 setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
119 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
121 std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
125 std::vector<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildren() const
127 std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildren());
129 ret.push_back(_nodal_connec);
130 if(_nodal_connec_index)
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 for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
251 if(nodeId>=nbOfNodes)
253 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes !";
254 throw INTERP_KERNEL::Exception(oss.str().c_str());
259 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " in connectivity ! sounds bad !";
260 throw INTERP_KERNEL::Exception(oss.str().c_str());
264 if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
266 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #-1 in connectivity ! sounds bad !";
267 throw INTERP_KERNEL::Exception(oss.str().c_str());
276 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
277 * then \a this mesh is most probably is writable, exchangeable and available for all
278 * algorithms. <br> This method performs the same checks as checkCoherency1() does.
279 * \param [in] eps - a not used parameter.
280 * \throw If the mesh dimension is not set.
281 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
282 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
283 * \throw If the connectivity data array has more than one component.
284 * \throw If the connectivity data array has a named component.
285 * \throw If the connectivity index data array has more than one component.
286 * \throw If the connectivity index data array has a named component.
287 * \throw If number of nodes defining an element does not correspond to the type of element.
288 * \throw If the nodal connectivity includes an invalid node id.
290 void MEDCouplingUMesh::checkCoherency2(double eps) const
292 checkCoherency1(eps);
296 * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
297 * elements contained in the mesh. For more info on the mesh dimension see
298 * \ref MEDCouplingUMeshPage.
299 * \param [in] meshDim - a new mesh dimension.
300 * \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
302 void MEDCouplingUMesh::setMeshDimension(int meshDim)
304 if(meshDim<-1 || meshDim>3)
305 throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
311 * Allocates memory to store an estimation of the given number of cells. Closer is the estimation to the number of cells effectively inserted,
312 * less will be the needs to realloc. If the number of cells to be inserted is not known simply put 0 to this parameter.
313 * If a nodal connectivity previouly existed before the call of this method, it will be reset.
315 * \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
317 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
318 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
320 void MEDCouplingUMesh::allocateCells(int nbOfCells)
323 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
324 if(_nodal_connec_index)
326 _nodal_connec_index->decrRef();
330 _nodal_connec->decrRef();
332 _nodal_connec_index=DataArrayInt::New();
333 _nodal_connec_index->reserve(nbOfCells+1);
334 _nodal_connec_index->pushBackSilent(0);
335 _nodal_connec=DataArrayInt::New();
336 _nodal_connec->reserve(2*nbOfCells);
342 * Appends a cell to the connectivity array. For deeper understanding what is
343 * happening see \ref MEDCouplingUMeshNodalConnectivity.
344 * \param [in] type - type of cell to add.
345 * \param [in] size - number of nodes constituting this cell.
346 * \param [in] nodalConnOfCell - the connectivity of the cell to add.
348 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
349 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
351 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
353 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
354 if(_nodal_connec_index==0)
355 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
356 if((int)cm.getDimension()==_mesh_dim)
359 if(size!=(int)cm.getNumberOfNodes())
361 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
362 oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
363 throw INTERP_KERNEL::Exception(oss.str().c_str());
365 int idx=_nodal_connec_index->back();
367 _nodal_connec_index->pushBackSilent(val);
368 _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
373 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
374 oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
375 oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
376 throw INTERP_KERNEL::Exception(oss.str().c_str());
381 * Compacts data arrays to release unused memory. This method is to be called after
382 * finishing cell insertion using \a this->insertNextCell().
384 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
385 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
387 void MEDCouplingUMesh::finishInsertingCells()
389 _nodal_connec->pack();
390 _nodal_connec_index->pack();
391 _nodal_connec->declareAsNew();
392 _nodal_connec_index->declareAsNew();
397 * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
398 * Useful for python users.
400 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
402 return new MEDCouplingUMeshCellIterator(this);
406 * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
407 * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
408 * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
409 * Useful for python users.
411 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
413 if(!checkConsecutiveCellTypes())
414 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
415 return new MEDCouplingUMeshCellByTypeEntry(this);
419 * Returns a set of all cell types available in \a this mesh.
420 * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
421 * \warning this method does not throw any exception even if \a this is not defined.
422 * \sa MEDCouplingUMesh::getAllGeoTypesSorted
424 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
430 * This method returns the sorted list of geometric types in \a this.
431 * 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
432 * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
434 * \throw if connectivity in \a this is not correctly defined.
436 * \sa MEDCouplingMesh::getAllGeoTypes
438 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
440 std::vector<INTERP_KERNEL::NormalizedCellType> ret;
441 checkConnectivityFullyDefined();
442 int nbOfCells(getNumberOfCells());
445 if(getMeshLength()<1)
446 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
447 const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
448 ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
449 for(int i=1;i<nbOfCells;i++,ci++)
450 if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
451 ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
456 * This method is a method that compares \a this and \a other.
457 * This method compares \b all attributes, even names and component names.
459 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
462 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
463 std::ostringstream oss; oss.precision(15);
464 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
467 reason="mesh given in input is not castable in MEDCouplingUMesh !";
470 if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
472 if(_mesh_dim!=otherC->_mesh_dim)
474 oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" << otherC->_mesh_dim;
478 if(_types!=otherC->_types)
480 oss << "umesh geometric type mismatch :\nThis geometric types are :";
481 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
482 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
483 oss << "\nOther geometric types are :";
484 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
485 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
489 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
490 if(_nodal_connec==0 || otherC->_nodal_connec==0)
492 reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
495 if(_nodal_connec!=otherC->_nodal_connec)
496 if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
498 reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
501 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
502 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
504 reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
507 if(_nodal_connec_index!=otherC->_nodal_connec_index)
508 if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
510 reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
517 * Checks if data arrays of this mesh (node coordinates, nodal
518 * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
520 * \param [in] other - the mesh to compare with.
521 * \param [in] prec - precision value used to compare node coordinates.
522 * \return bool - \a true if the two meshes are same.
524 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
526 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
529 if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
531 if(_mesh_dim!=otherC->_mesh_dim)
533 if(_types!=otherC->_types)
535 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
536 if(_nodal_connec==0 || otherC->_nodal_connec==0)
538 if(_nodal_connec!=otherC->_nodal_connec)
539 if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
541 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
542 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
544 if(_nodal_connec_index!=otherC->_nodal_connec_index)
545 if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
551 * Checks if \a this and \a other meshes are geometrically equivalent with high
552 * probability, else an exception is thrown. The meshes are considered equivalent if
553 * (1) meshes contain the same number of nodes and the same number of elements of the
554 * same types (2) three cells of the two meshes (first, last and middle) are based
555 * on coincident nodes (with a specified precision).
556 * \param [in] other - the mesh to compare with.
557 * \param [in] prec - the precision used to compare nodes of the two meshes.
558 * \throw If the two meshes do not match.
560 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
562 MEDCouplingPointSet::checkFastEquivalWith(other,prec);
563 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
565 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !");
569 * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
570 * cells each node belongs to.
571 * \warning For speed reasons, this method does not check if node ids in the nodal
572 * connectivity correspond to the size of node coordinates array.
573 * \param [in,out] revNodal - an array holding ids of cells sharing each node.
574 * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
575 * dividing cell ids in \a revNodal into groups each referring to one
576 * node. Its every element (except the last one) is an index pointing to the
577 * first id of a group of cells. For example cells sharing the node #1 are
578 * described by following range of indices:
579 * [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
580 * \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
581 * Number of cells sharing the *i*-th node is
582 * \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
583 * \throw If the coordinates array is not set.
584 * \throw If the nodal connectivity of cells is not defined.
586 * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
587 * \ref py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
589 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
592 int nbOfNodes=getNumberOfNodes();
593 int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
594 revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
595 std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
596 const int *conn=_nodal_connec->getConstPointer();
597 const int *connIndex=_nodal_connec_index->getConstPointer();
598 int nbOfCells=getNumberOfCells();
599 int nbOfEltsInRevNodal=0;
600 for(int eltId=0;eltId<nbOfCells;eltId++)
602 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
603 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
604 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
605 if(*iter>=0)//for polyhedrons
607 nbOfEltsInRevNodal++;
608 revNodalIndxPtr[(*iter)+1]++;
611 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
612 int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
613 revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
614 std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
615 for(int eltId=0;eltId<nbOfCells;eltId++)
617 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
618 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
619 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
620 if(*iter>=0)//for polyhedrons
621 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
627 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
632 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
638 if(cm.getOrientationStatus(nb,conn1,conn2))
645 class MinusOneSonsGenerator
648 MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
649 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
650 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
651 static const int DELTA=1;
653 const INTERP_KERNEL::CellModel& _cm;
656 class MinusOneSonsGeneratorBiQuadratic
659 MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
660 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
661 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
662 static const int DELTA=1;
664 const INTERP_KERNEL::CellModel& _cm;
667 class MinusTwoSonsGenerator
670 MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
671 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
672 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
673 static const int DELTA=2;
675 const INTERP_KERNEL::CellModel& _cm;
681 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
682 * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
683 * describing correspondence between cells of \a this and the result meshes are
684 * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
685 * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
686 * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
687 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
688 * \warning For speed reasons, this method does not check if node ids in the nodal
689 * connectivity correspond to the size of node coordinates array.
690 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
691 * to write this mesh to the MED file, its cells must be sorted using
692 * sortCellsInMEDFileFrmt().
693 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
694 * each cell of \a this mesh.
695 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
696 * dividing cell ids in \a desc into groups each referring to one
697 * cell of \a this mesh. Its every element (except the last one) is an index
698 * pointing to the first id of a group of cells. For example cells of the
699 * result mesh bounding the cell #1 of \a this mesh are described by following
701 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
702 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
703 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
704 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
705 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
706 * by each cell of the result mesh.
707 * \param [in,out] revDescIndx - the array, of length one more than number of cells
708 * in the result mesh,
709 * dividing cell ids in \a revDesc into groups each referring to one
710 * cell of the result mesh the same way as \a descIndx divides \a desc.
711 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
712 * delete this mesh using decrRef() as it is no more needed.
713 * \throw If the coordinates array is not set.
714 * \throw If the nodal connectivity of cells is node defined.
715 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
716 * revDescIndx == NULL.
718 * \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
719 * \ref py_mcumesh_buildDescendingConnectivity "Here is a Python example".
720 * \sa buildDescendingConnectivity2()
722 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
724 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
728 * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
729 * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
730 * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
731 * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
732 * \sa MEDCouplingUMesh::buildDescendingConnectivity
734 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
737 if(getMeshDimension()!=3)
738 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
739 return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
743 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
744 * this->getMeshDimension(), that bound cells of \a this mesh. In
745 * addition arrays describing correspondence between cells of \a this and the result
746 * meshes are returned. The arrays \a desc and \a descIndx describe the descending
747 * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
748 * mesh. This method differs from buildDescendingConnectivity() in that apart
749 * from cell ids, \a desc returns mutual orientation of cells in \a this and the
750 * result meshes. So a positive id means that order of nodes in corresponding cells
751 * of two meshes is same, and a negative id means a reverse order of nodes. Since a
752 * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
753 * i.e. cell ids are one-based.
754 * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
755 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
756 * \warning For speed reasons, this method does not check if node ids in the nodal
757 * connectivity correspond to the size of node coordinates array.
758 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
759 * to write this mesh to the MED file, its cells must be sorted using
760 * sortCellsInMEDFileFrmt().
761 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
762 * each cell of \a this mesh.
763 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
764 * dividing cell ids in \a desc into groups each referring to one
765 * cell of \a this mesh. Its every element (except the last one) is an index
766 * pointing to the first id of a group of cells. For example cells of the
767 * result mesh bounding the cell #1 of \a this mesh are described by following
769 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
770 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
771 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
772 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
773 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
774 * by each cell of the result mesh.
775 * \param [in,out] revDescIndx - the array, of length one more than number of cells
776 * in the result mesh,
777 * dividing cell ids in \a revDesc into groups each referring to one
778 * cell of the result mesh the same way as \a descIndx divides \a desc.
779 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
780 * shares the node coordinates array with \a this mesh. The caller is to
781 * delete this mesh using decrRef() as it is no more needed.
782 * \throw If the coordinates array is not set.
783 * \throw If the nodal connectivity of cells is node defined.
784 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
785 * revDescIndx == NULL.
787 * \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
788 * \ref py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
789 * \sa buildDescendingConnectivity()
791 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
793 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
797 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
798 * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
799 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
800 * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
802 * \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
803 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
804 * \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.
806 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
808 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
809 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
810 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
811 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
812 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
814 ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
818 * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
819 * 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,
820 * excluding a set of meshdim-1 cells in input descending connectivity.
821 * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
822 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
823 * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
825 * \param [in] desc descending connectivity array.
826 * \param [in] descIndx descending connectivity index array used to walk through \b desc.
827 * \param [in] revDesc reverse descending connectivity array.
828 * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
829 * \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
830 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
831 * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
833 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
834 DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) throw(INTERP_KERNEL::Exception)
836 if(!desc || !descIndx || !revDesc || !revDescIndx)
837 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
838 const int *descPtr=desc->getConstPointer();
839 const int *descIPtr=descIndx->getConstPointer();
840 const int *revDescPtr=revDesc->getConstPointer();
841 const int *revDescIPtr=revDescIndx->getConstPointer();
843 int nbCells=descIndx->getNumberOfTuples()-1;
844 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
845 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
846 int *out1Ptr=out1->getPointer();
848 out0->reserve(desc->getNumberOfTuples());
849 for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
851 for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
853 std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
855 out0->insertAtTheEnd(s.begin(),s.end());
857 *out1Ptr=out0->getNumberOfTuples();
859 neighbors=out0.retn();
860 neighborsIndx=out1.retn();
866 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
867 * For speed reasons no check of this will be done.
869 template<class SonsGenerator>
870 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
872 if(!desc || !descIndx || !revDesc || !revDescIndx)
873 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
874 checkConnectivityFullyDefined();
875 int nbOfCells=getNumberOfCells();
876 int nbOfNodes=getNumberOfNodes();
877 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
878 int *revNodalIndxPtr=revNodalIndx->getPointer();
879 const int *conn=_nodal_connec->getConstPointer();
880 const int *connIndex=_nodal_connec_index->getConstPointer();
881 std::string name="Mesh constituent of "; name+=getName();
882 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA);
883 ret->setCoords(getCoords());
884 ret->allocateCells(2*nbOfCells);
885 descIndx->alloc(nbOfCells+1,1);
886 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
887 int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
888 for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
890 int pos=connIndex[eltId];
891 int posP1=connIndex[eltId+1];
892 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
893 SonsGenerator sg(cm);
894 unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
895 INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
896 for(unsigned i=0;i<nbOfSons;i++)
898 INTERP_KERNEL::NormalizedCellType cmsId;
899 unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
900 for(unsigned k=0;k<nbOfNodesSon;k++)
902 revNodalIndxPtr[tmp[k]+1]++;
903 ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
904 revDesc2->pushBackSilent(eltId);
906 descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
908 int nbOfCellsM1=ret->getNumberOfCells();
909 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
910 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
911 std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
912 int *revNodalPtr=revNodal->getPointer();
913 const int *connM1=ret->getNodalConnectivity()->getConstPointer();
914 const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
915 for(int eltId=0;eltId<nbOfCellsM1;eltId++)
917 const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
918 const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
919 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
920 if(*iter>=0)//for polyhedrons
921 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
924 DataArrayInt *commonCells=0,*commonCellsI=0;
925 FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
926 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
927 const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
928 int newNbOfCellsM1=-1;
929 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
930 commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
931 std::vector<bool> isImpacted(nbOfCellsM1,false);
932 for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
933 for(int work2=work[0];work2!=work[1];work2++)
934 isImpacted[commonCellsPtr[work2]]=true;
935 const int *o2nM1Ptr=o2nM1->getConstPointer();
936 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
937 const int *n2oM1Ptr=n2oM1->getConstPointer();
938 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
939 ret2->copyTinyInfoFrom(this);
940 desc->alloc(descIndx->back(),1);
941 int *descPtr=desc->getPointer();
942 const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
943 for(int i=0;i<nbOfCellsM1;i++,descPtr++)
946 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
949 if(i!=n2oM1Ptr[o2nM1Ptr[i]])
951 const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
952 *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
955 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
958 revDesc->reserve(newNbOfCellsM1);
959 revDescIndx->alloc(newNbOfCellsM1+1,1);
960 int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
961 const int *revDesc2Ptr=revDesc2->getConstPointer();
962 for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
964 int oldCellIdM1=n2oM1Ptr[i];
965 if(!isImpacted[oldCellIdM1])
967 revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
968 revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
972 for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
973 revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
974 revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
982 struct MEDCouplingAccVisit
984 MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
985 int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
986 int _new_nb_of_nodes;
992 * Converts specified cells to either polygons (if \a this is a 2D mesh) or
993 * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
994 * array of cell ids. Pay attention that after conversion all algorithms work slower
995 * with \a this mesh than before conversion. <br> If an exception is thrown during the
996 * conversion due presence of invalid ids in the array of cells to convert, as a
997 * result \a this mesh contains some already converted elements. In this case the 2D
998 * mesh remains valid but 3D mesh becomes \b inconsistent!
999 * \warning This method can significantly modify the order of geometric types in \a this,
1000 * hence, to write this mesh to the MED file, its cells must be sorted using
1001 * sortCellsInMEDFileFrmt().
1002 * \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1003 * \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1004 * cellIdsToConvertBg.
1005 * \throw If the coordinates array is not set.
1006 * \throw If the nodal connectivity of cells is node defined.
1007 * \throw If dimension of \a this mesh is not either 2 or 3.
1009 * \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1010 * \ref py_mcumesh_convertToPolyTypes "Here is a Python example".
1012 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1014 checkFullyDefined();
1015 int dim=getMeshDimension();
1017 throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1018 int nbOfCells(getNumberOfCells());
1021 const int *connIndex=_nodal_connec_index->getConstPointer();
1022 int *conn=_nodal_connec->getPointer();
1023 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1025 if(*iter>=0 && *iter<nbOfCells)
1027 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1028 if(!cm.isQuadratic())
1029 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1031 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1035 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1036 oss << " in range [0," << nbOfCells << ") !";
1037 throw INTERP_KERNEL::Exception(oss.str().c_str());
1043 int *connIndex=_nodal_connec_index->getPointer();
1044 int connIndexLgth=_nodal_connec_index->getNbOfElems();
1045 const int *connOld=_nodal_connec->getConstPointer();
1046 int connOldLgth=_nodal_connec->getNbOfElems();
1047 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1048 std::vector<bool> toBeDone(nbOfCells,false);
1049 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1051 if(*iter>=0 && *iter<nbOfCells)
1052 toBeDone[*iter]=true;
1055 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1056 oss << " in range [0," << nbOfCells << ") !";
1057 throw INTERP_KERNEL::Exception(oss.str().c_str());
1060 for(int cellId=0;cellId<nbOfCells;cellId++)
1062 int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1063 int lgthOld(posP1-pos-1);
1064 if(toBeDone[cellId])
1066 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1067 unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1068 int *tmp(new int[nbOfFaces*lgthOld+1]);
1069 int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1070 for(unsigned j=0;j<nbOfFaces;j++)
1072 INTERP_KERNEL::NormalizedCellType type;
1073 unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1077 std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1078 connNew->pushBackValsSilent(tmp,tmp+newLgth);
1079 connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1084 connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1085 connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1088 setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1094 * Converts all cells to either polygons (if \a this is a 2D mesh) or
1095 * polyhedrons (if \a this is a 3D mesh).
1096 * \warning As this method is purely for user-friendliness and no optimization is
1097 * done to avoid construction of a useless vector, this method can be costly
1099 * \throw If the coordinates array is not set.
1100 * \throw If the nodal connectivity of cells is node defined.
1101 * \throw If dimension of \a this mesh is not either 2 or 3.
1103 void MEDCouplingUMesh::convertAllToPoly()
1105 int nbOfCells=getNumberOfCells();
1106 std::vector<int> cellIds(nbOfCells);
1107 for(int i=0;i<nbOfCells;i++)
1109 convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1113 * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1114 * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1115 * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1116 * base facet of the volume and the second half of nodes describes an opposite facet
1117 * having the same number of nodes as the base one. This method converts such
1118 * connectivity to a valid polyhedral format where connectivity of each facet is
1119 * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1120 * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1121 * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1122 * a correct orientation of the first facet of a polyhedron, else orientation of a
1123 * corrected cell is reverse.<br>
1124 * This method is useful to build an extruded unstructured mesh with polyhedrons as
1125 * it releases the user from boring description of polyhedra connectivity in the valid
1127 * \throw If \a this->getMeshDimension() != 3.
1128 * \throw If \a this->getSpaceDimension() != 3.
1129 * \throw If the nodal connectivity of cells is not defined.
1130 * \throw If the coordinates array is not set.
1131 * \throw If \a this mesh contains polyhedrons with the valid connectivity.
1132 * \throw If \a this mesh contains polyhedrons with odd number of nodes.
1134 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1135 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1137 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1139 checkFullyDefined();
1140 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1141 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1142 int nbOfCells=getNumberOfCells();
1143 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1144 newCi->alloc(nbOfCells+1,1);
1145 int *newci=newCi->getPointer();
1146 const int *ci=_nodal_connec_index->getConstPointer();
1147 const int *c=_nodal_connec->getConstPointer();
1149 for(int i=0;i<nbOfCells;i++)
1151 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1152 if(type==INTERP_KERNEL::NORM_POLYHED)
1154 if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1156 std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1157 throw INTERP_KERNEL::Exception(oss.str().c_str());
1159 std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1162 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 !";
1163 throw INTERP_KERNEL::Exception(oss.str().c_str());
1166 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)
1169 newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1171 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1172 newC->alloc(newci[nbOfCells],1);
1173 int *newc=newC->getPointer();
1174 for(int i=0;i<nbOfCells;i++)
1176 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1177 if(type==INTERP_KERNEL::NORM_POLYHED)
1179 std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1180 newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1182 for(std::size_t j=0;j<n1;j++)
1184 newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1186 newc[n1+5*j+1]=c[ci[i]+1+j];
1187 newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1188 newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1189 newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1194 newc=std::copy(c+ci[i],c+ci[i+1],newc);
1196 _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1197 _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1202 * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1203 * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1204 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1205 * to write this mesh to the MED file, its cells must be sorted using
1206 * sortCellsInMEDFileFrmt().
1207 * \return \c true if at least one cell has been converted, \c false else. In the
1208 * last case the nodal connectivity remains unchanged.
1209 * \throw If the coordinates array is not set.
1210 * \throw If the nodal connectivity of cells is not defined.
1211 * \throw If \a this->getMeshDimension() < 0.
1213 bool MEDCouplingUMesh::unPolyze()
1215 checkFullyDefined();
1216 int mdim=getMeshDimension();
1218 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1221 int nbOfCells=getNumberOfCells();
1224 int initMeshLgth=getMeshLength();
1225 int *conn=_nodal_connec->getPointer();
1226 int *index=_nodal_connec_index->getPointer();
1231 for(int i=0;i<nbOfCells;i++)
1233 lgthOfCurCell=index[i+1]-posOfCurCell;
1234 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1235 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1236 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1240 switch(cm.getDimension())
1244 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1245 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1246 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1251 int nbOfFaces,lgthOfPolyhConn;
1252 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1253 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1258 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1262 ret=ret || (newType!=type);
1263 conn[newPos]=newType;
1265 posOfCurCell=index[i+1];
1270 std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1271 newPos+=lgthOfCurCell;
1272 posOfCurCell+=lgthOfCurCell;
1276 if(newPos!=initMeshLgth)
1277 _nodal_connec->reAlloc(newPos);
1284 * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1285 * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1286 * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells.
1288 * \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
1291 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1293 checkFullyDefined();
1294 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1295 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1296 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1297 coords->recenterForMaxPrecision(eps);
1299 int nbOfCells=getNumberOfCells();
1300 const int *conn=_nodal_connec->getConstPointer();
1301 const int *index=_nodal_connec_index->getConstPointer();
1302 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1303 connINew->alloc(nbOfCells+1,1);
1304 int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1305 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1307 for(int i=0;i<nbOfCells;i++,connINewPtr++)
1309 if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1311 SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1315 connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1316 *connINewPtr=connNew->getNumberOfTuples();
1319 setConnectivity(connNew,connINew,false);
1323 * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1324 * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1325 * the format of returned DataArrayInt instance.
1327 * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1328 * \sa MEDCouplingUMesh::getNodeIdsInUse
1330 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1332 checkConnectivityFullyDefined();
1333 int nbOfCells=getNumberOfCells();
1334 const int *connIndex=_nodal_connec_index->getConstPointer();
1335 const int *conn=_nodal_connec->getConstPointer();
1336 const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1337 int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1338 std::vector<bool> retS(maxElt,false);
1339 for(int i=0;i<nbOfCells;i++)
1340 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1344 for(int i=0;i<maxElt;i++)
1347 DataArrayInt *ret=DataArrayInt::New();
1349 int *retPtr=ret->getPointer();
1350 for(int i=0;i<maxElt;i++)
1357 * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1358 * \sa MEDCouplingUMesh::getNodeIdsInUse
1360 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1362 int nbOfNodes=(int)nodeIdsInUse.size();
1363 int nbOfCells=getNumberOfCells();
1364 const int *connIndex=_nodal_connec_index->getConstPointer();
1365 const int *conn=_nodal_connec->getConstPointer();
1366 for(int i=0;i<nbOfCells;i++)
1367 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1370 if(conn[j]<nbOfNodes)
1371 nodeIdsInUse[conn[j]]=true;
1374 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1375 throw INTERP_KERNEL::Exception(oss.str().c_str());
1381 * Finds nodes not used in any cell and returns an array giving a new id to every node
1382 * by excluding the unused nodes, for which the array holds -1. The result array is
1383 * a mapping in "Old to New" mode.
1384 * \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1385 * \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1386 * this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1387 * if the node is unused or a new id else. The caller is to delete this
1388 * array using decrRef() as it is no more needed.
1389 * \throw If the coordinates array is not set.
1390 * \throw If the nodal connectivity of cells is not defined.
1391 * \throw If the nodal connectivity includes an invalid id.
1393 * \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1394 * \ref py_mcumesh_getNodeIdsInUse "Here is a Python example".
1395 * \sa computeNodeIdsAlg()
1397 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1400 int nbOfNodes=getNumberOfNodes();
1401 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1402 ret->alloc(nbOfNodes,1);
1403 int *traducer=ret->getPointer();
1404 std::fill(traducer,traducer+nbOfNodes,-1);
1405 int nbOfCells=getNumberOfCells();
1406 const int *connIndex=_nodal_connec_index->getConstPointer();
1407 const int *conn=_nodal_connec->getConstPointer();
1408 for(int i=0;i<nbOfCells;i++)
1409 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1412 if(conn[j]<nbOfNodes)
1413 traducer[conn[j]]=1;
1416 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1417 throw INTERP_KERNEL::Exception(oss.str().c_str());
1420 nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1421 std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1426 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1427 * For each cell in \b this the number of nodes constituting cell is computed.
1428 * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1429 * So for pohyhedrons some nodes can be counted several times in the returned result.
1431 * \return a newly allocated array
1432 * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1434 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1436 checkConnectivityFullyDefined();
1437 int nbOfCells=getNumberOfCells();
1438 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1439 ret->alloc(nbOfCells,1);
1440 int *retPtr=ret->getPointer();
1441 const int *conn=getNodalConnectivity()->getConstPointer();
1442 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1443 for(int i=0;i<nbOfCells;i++,retPtr++)
1445 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1446 *retPtr=connI[i+1]-connI[i]-1;
1448 *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1454 * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1455 * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1457 * \return DataArrayInt * - new object to be deallocated by the caller.
1458 * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1460 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1462 checkConnectivityFullyDefined();
1463 int nbOfCells=getNumberOfCells();
1464 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1465 ret->alloc(nbOfCells,1);
1466 int *retPtr=ret->getPointer();
1467 const int *conn=getNodalConnectivity()->getConstPointer();
1468 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1469 for(int i=0;i<nbOfCells;i++,retPtr++)
1471 std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1472 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1473 *retPtr=(int)s.size();
1477 *retPtr=(int)s.size();
1484 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1485 * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1487 * \return a newly allocated array
1489 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1491 checkConnectivityFullyDefined();
1492 int nbOfCells=getNumberOfCells();
1493 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1494 ret->alloc(nbOfCells,1);
1495 int *retPtr=ret->getPointer();
1496 const int *conn=getNodalConnectivity()->getConstPointer();
1497 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1498 for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1500 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1501 *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1507 * Removes unused nodes (the node coordinates array is shorten) and returns an array
1508 * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1509 * array mean that the corresponding old node is no more used.
1510 * \return DataArrayInt * - a new instance of DataArrayInt of length \a
1511 * this->getNumberOfNodes() before call of this method. The caller is to
1512 * delete this array using decrRef() as it is no more needed.
1513 * \throw If the coordinates array is not set.
1514 * \throw If the nodal connectivity of cells is not defined.
1515 * \throw If the nodal connectivity includes an invalid id.
1517 * \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1518 * \ref py_mcumesh_zipCoordsTraducer "Here is a Python example".
1520 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1522 return MEDCouplingPointSet::zipCoordsTraducer();
1526 * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1527 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1529 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1534 return AreCellsEqual0(conn,connI,cell1,cell2);
1536 return AreCellsEqual1(conn,connI,cell1,cell2);
1538 return AreCellsEqual2(conn,connI,cell1,cell2);
1540 return AreCellsEqual3(conn,connI,cell1,cell2);
1542 return AreCellsEqual7(conn,connI,cell1,cell2);
1544 throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1548 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1550 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1552 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1553 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1558 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1560 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1562 int sz=connI[cell1+1]-connI[cell1];
1563 if(sz==connI[cell2+1]-connI[cell2])
1565 if(conn[connI[cell1]]==conn[connI[cell2]])
1567 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1568 unsigned dim=cm.getDimension();
1574 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1575 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1576 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1577 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1578 return work!=tmp+sz1?1:0;
1581 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1584 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1591 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1593 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1595 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1597 if(conn[connI[cell1]]==conn[connI[cell2]])
1599 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1600 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1608 * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1610 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1612 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1614 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1615 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1622 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1624 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1626 int sz=connI[cell1+1]-connI[cell1];
1627 if(sz==connI[cell2+1]-connI[cell2])
1629 if(conn[connI[cell1]]==conn[connI[cell2]])
1631 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1632 unsigned dim=cm.getDimension();
1638 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1639 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1640 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1641 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1646 std::reverse_iterator<int *> it1((int *)tmp+sz1);
1647 std::reverse_iterator<int *> it2((int *)tmp);
1648 if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1654 return work!=tmp+sz1?1:0;
1657 {//case of SEG2 and SEG3
1658 if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1660 if(!cm.isQuadratic())
1662 std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1663 std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1664 if(std::equal(it1,it2,conn+connI[cell2]+1))
1670 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])
1677 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1684 * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1685 * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1686 * and result remains unchanged.
1687 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1688 * If in 'candidates' pool -1 value is considered as an empty value.
1689 * WARNING this method returns only ONE set of result !
1691 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1693 if(candidates.size()<1)
1696 std::vector<int>::const_iterator iter=candidates.begin();
1697 int start=(*iter++);
1698 for(;iter!=candidates.end();iter++)
1700 int status=AreCellsEqual(conn,connI,start,*iter,compType);
1705 result->pushBackSilent(start);
1709 result->pushBackSilent(*iter);
1711 result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1718 * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1719 * This method keeps the coordiantes of \a this. This method is time consuming and is called
1721 * \param [in] compType input specifying the technique used to compare cells each other.
1722 * - 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.
1723 * - 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)
1724 * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1725 * - 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
1726 * can be used for users not sensitive to orientation of cell
1727 * \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.
1728 * \param [out] commonCells
1729 * \param [out] commonCellsI
1730 * \return the correspondance array old to new in a newly allocated array.
1733 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1735 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1736 getReverseNodalConnectivity(revNodal,revNodalI);
1737 FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1740 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1741 DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) throw(INTERP_KERNEL::Exception)
1743 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1744 int nbOfCells=nodalI->getNumberOfTuples()-1;
1745 commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1746 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1747 const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1748 std::vector<bool> isFetched(nbOfCells,false);
1751 for(int i=0;i<nbOfCells;i++)
1755 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1756 std::vector<int> v,v2;
1757 if(connOfNode!=connPtr+connIPtr[i+1])
1759 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1760 v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1763 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1767 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1768 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1769 v2.resize(std::distance(v2.begin(),it));
1773 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1775 int pos=commonCellsI->back();
1776 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1777 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1778 isFetched[*it]=true;
1786 for(int i=startCellId;i<nbOfCells;i++)
1790 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1791 std::vector<int> v,v2;
1792 if(connOfNode!=connPtr+connIPtr[i+1])
1794 v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1797 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1801 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1802 v2.resize(std::distance(v2.begin(),it));
1806 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1808 int pos=commonCellsI->back();
1809 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1810 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1811 isFetched[*it]=true;
1817 commonCellsArr=commonCells.retn();
1818 commonCellsIArr=commonCellsI.retn();
1822 * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1823 * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1824 * than \a other->getNumberOfCells() in the returned array means that there is no
1825 * corresponding cell in \a this mesh.
1826 * It is expected that \a this and \a other meshes share the same node coordinates
1827 * array, if it is not so an exception is thrown.
1828 * \param [in] other - the mesh to compare with.
1829 * \param [in] compType - specifies a cell comparison technique. For meaning of its
1830 * valid values [0,1,2], see zipConnectivityTraducer().
1831 * \param [out] arr - a new instance of DataArrayInt returning correspondence
1832 * between cells of the two meshes. It contains \a other->getNumberOfCells()
1833 * values. The caller is to delete this array using
1834 * decrRef() as it is no more needed.
1835 * \return bool - \c true if all cells of \a other mesh are present in the \a this
1838 * \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1839 * \ref py_mcumesh_areCellsIncludedIn "Here is a Python example".
1840 * \sa checkDeepEquivalOnSameNodesWith()
1841 * \sa checkGeoEquivalWith()
1843 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1845 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1846 int nbOfCells=getNumberOfCells();
1847 static const int possibleCompType[]={0,1,2};
1848 if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1850 std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1851 std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1853 throw INTERP_KERNEL::Exception(oss.str().c_str());
1855 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1856 arr=o2n->substr(nbOfCells);
1857 arr->setName(other->getName());
1859 if(other->getNumberOfCells()==0)
1861 return arr->getMaxValue(tmp)<nbOfCells;
1865 * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1866 * This method tries to determine if \b other is fully included in \b this.
1867 * The main difference is that this method is not expected to throw exception.
1868 * This method has two outputs :
1870 * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1871 * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1873 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1875 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1876 DataArrayInt *commonCells=0,*commonCellsI=0;
1877 int thisNbCells=getNumberOfCells();
1878 mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1879 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1880 const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1881 int otherNbCells=other->getNumberOfCells();
1882 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1883 arr2->alloc(otherNbCells,1);
1884 arr2->fillWithZero();
1885 int *arr2Ptr=arr2->getPointer();
1886 int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1887 for(int i=0;i<nbOfCommon;i++)
1889 int start=commonCellsPtr[commonCellsIPtr[i]];
1890 if(start<thisNbCells)
1892 for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1894 int sig=commonCellsPtr[j]>0?1:-1;
1895 int val=std::abs(commonCellsPtr[j])-1;
1896 if(val>=thisNbCells)
1897 arr2Ptr[val-thisNbCells]=sig*(start+1);
1901 arr2->setName(other->getName());
1902 if(arr2->presenceOfValue(0))
1908 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1911 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1912 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1914 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1915 std::vector<const MEDCouplingUMesh *> ms(2);
1918 return MergeUMeshesOnSameCoords(ms);
1922 * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1923 * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1924 * cellIds is not given explicitely but by a range python like.
1926 * \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.
1927 * \return a newly allocated
1929 * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1930 * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1932 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const
1934 if(getMeshDimension()!=-1)
1935 return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
1938 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
1940 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1942 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1944 return const_cast<MEDCouplingUMesh *>(this);
1949 * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
1950 * The result mesh shares or not the node coordinates array with \a this mesh depending
1951 * on \a keepCoords parameter.
1952 * \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
1953 * to write this mesh to the MED file, its cells must be sorted using
1954 * sortCellsInMEDFileFrmt().
1955 * \param [in] begin - an array of cell ids to include to the new mesh.
1956 * \param [in] end - a pointer to last-plus-one-th element of \a begin.
1957 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
1958 * array of \a this mesh, else "free" nodes are removed from the result mesh
1959 * by calling zipCoords().
1960 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
1961 * to delete this mesh using decrRef() as it is no more needed.
1962 * \throw If the coordinates array is not set.
1963 * \throw If the nodal connectivity of cells is not defined.
1964 * \throw If any cell id in the array \a begin is not valid.
1966 * \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
1967 * \ref py_mcumesh_buildPartOfMySelf "Here is a Python example".
1969 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
1971 if(getMeshDimension()!=-1)
1972 return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
1976 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1978 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1980 return const_cast<MEDCouplingUMesh *>(this);
1985 * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
1987 * 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.
1988 * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
1989 * The number of cells of \b this will remain the same with this method.
1991 * \param [in] begin begin of cell ids (included) of cells in this to assign
1992 * \param [in] end end of cell ids (excluded) of cells in this to assign
1993 * \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 ).
1994 * Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
1996 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
1998 checkConnectivityFullyDefined();
1999 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2000 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2001 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2002 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2004 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2005 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2006 throw INTERP_KERNEL::Exception(oss.str().c_str());
2008 int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2009 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2011 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2012 throw INTERP_KERNEL::Exception(oss.str().c_str());
2014 int nbOfCells=getNumberOfCells();
2015 bool easyAssign=true;
2016 const int *connI=_nodal_connec_index->getConstPointer();
2017 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2018 for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2020 if(*it>=0 && *it<nbOfCells)
2022 easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2026 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2027 throw INTERP_KERNEL::Exception(oss.str().c_str());
2032 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2037 DataArrayInt *arrOut=0,*arrIOut=0;
2038 MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2040 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2041 setConnectivity(arrOut,arrIOut,true);
2045 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2047 checkConnectivityFullyDefined();
2048 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2049 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2050 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2051 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2053 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2054 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2055 throw INTERP_KERNEL::Exception(oss.str().c_str());
2057 int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2058 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2060 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2061 throw INTERP_KERNEL::Exception(oss.str().c_str());
2063 int nbOfCells=getNumberOfCells();
2064 bool easyAssign=true;
2065 const int *connI=_nodal_connec_index->getConstPointer();
2066 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2068 for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2070 if(it>=0 && it<nbOfCells)
2072 easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2076 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2077 throw INTERP_KERNEL::Exception(oss.str().c_str());
2082 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2087 DataArrayInt *arrOut=0,*arrIOut=0;
2088 MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2090 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2091 setConnectivity(arrOut,arrIOut,true);
2096 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2097 * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2098 * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2099 * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2101 * \param [in] begin input start of array of node ids.
2102 * \param [in] end input end of array of node ids.
2103 * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2104 * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2106 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2108 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2109 checkConnectivityFullyDefined();
2111 int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2112 std::vector<bool> fastFinder(sz,false);
2113 for(const int *work=begin;work!=end;work++)
2114 if(*work>=0 && *work<sz)
2115 fastFinder[*work]=true;
2116 int nbOfCells=getNumberOfCells();
2117 const int *conn=getNodalConnectivity()->getConstPointer();
2118 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2119 for(int i=0;i<nbOfCells;i++)
2121 int ref=0,nbOfHit=0;
2122 for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2126 if(fastFinder[*work2])
2129 if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2130 cellIdsKept->pushBackSilent(i);
2132 cellIdsKeptArr=cellIdsKept.retn();
2136 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2137 * this->getMeshDimension(), that bound some cells of \a this mesh.
2138 * The cells of lower dimension to include to the result mesh are selected basing on
2139 * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2140 * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2141 * ==\c false, a cell is copied if any its node is in the array of node ids. The
2142 * created mesh shares the node coordinates array with \a this mesh.
2143 * \param [in] begin - the array of node ids.
2144 * \param [in] end - a pointer to the (last+1)-th element of \a begin.
2145 * \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2146 * array \a begin are added, else cells whose any node is in the
2147 * array \a begin are added.
2148 * \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2149 * to delete this mesh using decrRef() as it is no more needed.
2150 * \throw If the coordinates array is not set.
2151 * \throw If the nodal connectivity of cells is not defined.
2152 * \throw If any node id in \a begin is not valid.
2154 * \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2155 * \ref py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2157 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2159 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2160 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2161 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2162 desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2163 return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2167 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2168 * this->getMeshDimension(), which bound only one cell of \a this mesh.
2169 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2170 * array of \a this mesh, else "free" nodes are removed from the result mesh
2171 * by calling zipCoords().
2172 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2173 * to delete this mesh using decrRef() as it is no more needed.
2174 * \throw If the coordinates array is not set.
2175 * \throw If the nodal connectivity of cells is not defined.
2177 * \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2178 * \ref py_mcumesh_buildBoundaryMesh "Here is a Python example".
2180 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2182 DataArrayInt *desc=DataArrayInt::New();
2183 DataArrayInt *descIndx=DataArrayInt::New();
2184 DataArrayInt *revDesc=DataArrayInt::New();
2185 DataArrayInt *revDescIndx=DataArrayInt::New();
2187 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2190 descIndx->decrRef();
2191 int nbOfCells=meshDM1->getNumberOfCells();
2192 const int *revDescIndxC=revDescIndx->getConstPointer();
2193 std::vector<int> boundaryCells;
2194 for(int i=0;i<nbOfCells;i++)
2195 if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2196 boundaryCells.push_back(i);
2197 revDescIndx->decrRef();
2198 MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2203 * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2204 * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2205 * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown.
2207 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2209 checkFullyDefined();
2210 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2211 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2212 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2213 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2215 buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2216 desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2218 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2219 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2220 const int *revDescPtr=revDesc->getConstPointer();
2221 const int *revDescIndxPtr=revDescIndx->getConstPointer();
2222 int nbOfCells=getNumberOfCells();
2223 std::vector<bool> ret1(nbOfCells,false);
2225 for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2226 if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2227 { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2229 DataArrayInt *ret2=DataArrayInt::New();
2231 int *ret2Ptr=ret2->getPointer();
2233 for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2236 ret2->setName("BoundaryCells");
2241 * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2242 * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2243 * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2244 * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2246 * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2247 * This method method returns cells ids set s = s1 + s2 where :
2249 * - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2250 * - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2252 * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2253 * are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2255 * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2256 * \param [out] cellIdsRk1 a newly allocated array containing cells ids of s1+s2 \b into \b cellIdsRk0 subset. To get absolute ids of s1+s2 simply invoke
2257 * cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2259 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2261 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2262 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2263 checkConnectivityFullyDefined();
2264 otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2265 if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2266 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2267 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2268 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2269 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2270 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2271 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2272 const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2273 DataArrayInt *idsOtherInConsti=0;
2274 bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2275 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2277 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2279 for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2280 s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2281 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2282 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2283 DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2284 ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2285 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2286 ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2287 neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2288 RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2289 neighThisPartAuto=0;
2290 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2291 const int li[2]={0,1};
2292 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2293 s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2294 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2297 cellIdsRk0=s0arr.retn();
2298 cellIdsRk1=s_renum1.retn();
2302 * 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
2303 * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2305 * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2307 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2309 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2310 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2311 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2312 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2314 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2315 revDesc=0; desc=0; descIndx=0;
2316 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2317 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2318 return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2322 * Finds nodes lying on the boundary of \a this mesh.
2323 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2324 * nodes. The caller is to delete this array using decrRef() as it is no
2326 * \throw If the coordinates array is not set.
2327 * \throw If the nodal connectivity of cells is node defined.
2329 * \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2330 * \ref py_mcumesh_findBoundaryNodes "Here is a Python example".
2332 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2334 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2335 return skin->computeFetchedNodeIds();
2338 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2341 return const_cast<MEDCouplingUMesh *>(this);
2345 * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2346 * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2347 * 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.
2348 * 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.
2349 * 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.
2351 * \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
2352 * parameter is altered during the call.
2353 * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2354 * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2355 * \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.
2357 * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2359 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2360 DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const throw(INTERP_KERNEL::Exception)
2362 checkFullyDefined();
2363 otherDimM1OnSameCoords.checkFullyDefined();
2364 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2365 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2366 if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2367 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2368 DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2369 findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2370 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2371 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2372 s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2373 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2374 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2375 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2376 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2377 cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2379 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2380 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2381 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2382 DataArrayInt *idsTmp=0;
2383 bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2384 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2386 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2387 MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2388 DataArrayInt *tmp0=0,*tmp1=0;
2389 ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2390 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2391 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2392 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2393 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2394 cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2395 cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2397 cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2398 cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2399 nodeIdsToDuplicate=s3.retn();
2403 * This method operates a modification of the connectivity and coords in \b this.
2404 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2405 * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2406 * 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
2407 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2408 * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2410 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2412 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2413 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2415 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2417 int nbOfNodes=getNumberOfNodes();
2418 duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2419 duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2423 * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2424 * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2425 * This method is a generalization of shiftNodeNumbersInConn().
2426 * \warning This method performs no check of validity of new ids. **Use it with care !**
2427 * \param [in] newNodeNumbersO2N - a permutation array, of length \a
2428 * this->getNumberOfNodes(), in "Old to New" mode.
2429 * See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2430 * \throw If the nodal connectivity of cells is not defined.
2432 * \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2433 * \ref py_mcumesh_renumberNodesInConn "Here is a Python example".
2435 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2437 checkConnectivityFullyDefined();
2438 int *conn=getNodalConnectivity()->getPointer();
2439 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2440 int nbOfCells=getNumberOfCells();
2441 for(int i=0;i<nbOfCells;i++)
2442 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2444 int& node=conn[iconn];
2445 if(node>=0)//avoid polyhedron separator
2447 node=newNodeNumbersO2N[node];
2450 _nodal_connec->declareAsNew();
2455 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2456 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2457 * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2459 * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2461 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2463 checkConnectivityFullyDefined();
2464 int *conn=getNodalConnectivity()->getPointer();
2465 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2466 int nbOfCells=getNumberOfCells();
2467 for(int i=0;i<nbOfCells;i++)
2468 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2470 int& node=conn[iconn];
2471 if(node>=0)//avoid polyhedron separator
2476 _nodal_connec->declareAsNew();
2481 * This method operates a modification of the connectivity in \b this.
2482 * 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.
2483 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2484 * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2485 * 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
2486 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2487 * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2489 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2490 * As an another consequense after the call of this method \b this can be transiently non cohrent.
2492 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2493 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2494 * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ).
2496 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2498 checkConnectivityFullyDefined();
2499 std::map<int,int> m;
2501 for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2503 int *conn=getNodalConnectivity()->getPointer();
2504 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2505 int nbOfCells=getNumberOfCells();
2506 for(int i=0;i<nbOfCells;i++)
2507 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2509 int& node=conn[iconn];
2510 if(node>=0)//avoid polyhedron separator
2512 std::map<int,int>::iterator it=m.find(node);
2521 * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2523 * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2524 * After the call of this method the number of cells remains the same as before.
2526 * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2527 * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2528 * be strictly in [0;this->getNumberOfCells()).
2530 * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2531 * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2532 * should be contained in[0;this->getNumberOfCells()).
2534 * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2536 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2538 checkConnectivityFullyDefined();
2539 int nbCells=getNumberOfCells();
2540 const int *array=old2NewBg;
2542 array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2544 const int *conn=_nodal_connec->getConstPointer();
2545 const int *connI=_nodal_connec_index->getConstPointer();
2546 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2547 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2548 const int *n2oPtr=n2o->begin();
2549 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2550 newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2551 newConn->copyStringInfoFrom(*_nodal_connec);
2552 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2553 newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2554 newConnI->copyStringInfoFrom(*_nodal_connec_index);
2556 int *newC=newConn->getPointer();
2557 int *newCI=newConnI->getPointer();
2560 for(int i=0;i<nbCells;i++)
2563 int nbOfElts=connI[pos+1]-connI[pos];
2564 newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2569 setConnectivity(newConn,newConnI);
2571 free(const_cast<int *>(array));
2575 * Finds cells whose bounding boxes intersect a given bounding box.
2576 * \param [in] bbox - an array defining the bounding box via coordinates of its
2577 * extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2579 * \param [in] eps - a factor used to increase size of the bounding box of cell
2580 * before comparing it with \a bbox. This factor is multiplied by the maximal
2581 * extent of the bounding box of cell to produce an addition to this bounding box.
2582 * \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2583 * cells. The caller is to delete this array using decrRef() as it is no more
2585 * \throw If the coordinates array is not set.
2586 * \throw If the nodal connectivity of cells is not defined.
2588 * \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2589 * \ref py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2591 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2593 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2594 if(getMeshDimension()==-1)
2596 elems->pushBackSilent(0);
2597 return elems.retn();
2599 int dim=getSpaceDimension();
2600 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2601 const int* conn = getNodalConnectivity()->getConstPointer();
2602 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2603 const double* coords = getCoords()->getConstPointer();
2604 int nbOfCells=getNumberOfCells();
2605 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2607 for (int i=0; i<dim; i++)
2609 elem_bb[i*2]=std::numeric_limits<double>::max();
2610 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2613 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2615 int node= conn[inode];
2616 if(node>=0)//avoid polyhedron separator
2618 for (int idim=0; idim<dim; idim++)
2620 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2622 elem_bb[idim*2] = coords[node*dim+idim] ;
2624 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2626 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2631 if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2632 elems->pushBackSilent(ielem);
2634 return elems.retn();
2638 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2639 * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2640 * added in 'elems' parameter.
2642 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2644 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2645 if(getMeshDimension()==-1)
2647 elems->pushBackSilent(0);
2648 return elems.retn();
2650 int dim=getSpaceDimension();
2651 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2652 const int* conn = getNodalConnectivity()->getConstPointer();
2653 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2654 const double* coords = getCoords()->getConstPointer();
2655 int nbOfCells=getNumberOfCells();
2656 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2658 for (int i=0; i<dim; i++)
2660 elem_bb[i*2]=std::numeric_limits<double>::max();
2661 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2664 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2666 int node= conn[inode];
2667 if(node>=0)//avoid polyhedron separator
2669 for (int idim=0; idim<dim; idim++)
2671 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2673 elem_bb[idim*2] = coords[node*dim+idim] ;
2675 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2677 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2682 if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2683 elems->pushBackSilent(ielem);
2685 return elems.retn();
2689 * Returns a type of a cell by its id.
2690 * \param [in] cellId - the id of the cell of interest.
2691 * \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2692 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2694 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2696 const int *ptI=_nodal_connec_index->getConstPointer();
2697 const int *pt=_nodal_connec->getConstPointer();
2698 if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2699 return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2702 std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2703 throw INTERP_KERNEL::Exception(oss.str().c_str());
2708 * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2709 * This method does not throw exception if geometric type \a type is not in \a this.
2710 * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2711 * The coordinates array is not considered here.
2713 * \param [in] type the geometric type
2714 * \return cell ids in this having geometric type \a type.
2716 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2719 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2721 checkConnectivityFullyDefined();
2722 int nbCells=getNumberOfCells();
2723 int mdim=getMeshDimension();
2724 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2725 if(mdim!=(int)cm.getDimension())
2726 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2727 const int *ptI=_nodal_connec_index->getConstPointer();
2728 const int *pt=_nodal_connec->getConstPointer();
2729 for(int i=0;i<nbCells;i++)
2731 if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2732 ret->pushBackSilent(i);
2738 * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2740 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2742 const int *ptI=_nodal_connec_index->getConstPointer();
2743 const int *pt=_nodal_connec->getConstPointer();
2744 int nbOfCells=getNumberOfCells();
2746 for(int i=0;i<nbOfCells;i++)
2747 if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2753 * Returns the nodal connectivity of a given cell.
2754 * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2755 * all returned node ids can be used in getCoordinatesOfNode().
2756 * \param [in] cellId - an id of the cell of interest.
2757 * \param [in,out] conn - a vector where the node ids are appended. It is not
2758 * cleared before the appending.
2759 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2761 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2763 const int *ptI=_nodal_connec_index->getConstPointer();
2764 const int *pt=_nodal_connec->getConstPointer();
2765 for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2770 std::string MEDCouplingUMesh::simpleRepr() const
2772 static const char msg0[]="No coordinates specified !";
2773 std::ostringstream ret;
2774 ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2775 ret << "Description of mesh : \"" << getDescription() << "\"\n";
2777 double tt=getTime(tmpp1,tmpp2);
2778 ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2779 ret << "Iteration : " << tmpp1 << " Order : " << tmpp2 << "\n";
2781 { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2783 { ret << " Mesh dimension has not been set or is invalid !"; }
2786 const int spaceDim=getSpaceDimension();
2787 ret << spaceDim << "\nInfo attached on space dimension : ";
2788 for(int i=0;i<spaceDim;i++)
2789 ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2793 ret << msg0 << "\n";
2794 ret << "Number of nodes : ";
2796 ret << getNumberOfNodes() << "\n";
2798 ret << msg0 << "\n";
2799 ret << "Number of cells : ";
2800 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2801 ret << getNumberOfCells() << "\n";
2803 ret << "No connectivity specified !" << "\n";
2804 ret << "Cell types present : ";
2805 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2807 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2808 ret << cm.getRepr() << " ";
2814 std::string MEDCouplingUMesh::advancedRepr() const
2816 std::ostringstream ret;
2817 ret << simpleRepr();
2818 ret << "\nCoordinates array : \n___________________\n\n";
2820 _coords->reprWithoutNameStream(ret);
2822 ret << "No array set !\n";
2823 ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2824 reprConnectivityOfThisLL(ret);
2829 * This method returns a C++ code that is a dump of \a this.
2830 * This method will throw if this is not fully defined.
2832 std::string MEDCouplingUMesh::cppRepr() const
2834 static const char coordsName[]="coords";
2835 static const char connName[]="conn";
2836 static const char connIName[]="connI";
2837 checkFullyDefined();
2838 std::ostringstream ret; ret << "// coordinates" << std::endl;
2839 _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2840 _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2841 _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2842 ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2843 ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2844 ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2845 ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2849 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2851 std::ostringstream ret;
2852 reprConnectivityOfThisLL(ret);
2857 * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
2858 * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2859 * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2862 * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2863 * 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
2864 * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2866 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
2868 int mdim=getMeshDimension();
2870 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2871 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
2872 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
2873 bool needToCpyCT=true;
2876 tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2884 if(!_nodal_connec_index)
2886 tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2891 tmp2=_nodal_connec_index;
2894 ret->setConnectivity(tmp1,tmp2,false);
2899 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2900 ret->setCoords(coords);
2903 ret->setCoords(_coords);
2907 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
2909 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2911 int nbOfCells=getNumberOfCells();
2912 const int *c=_nodal_connec->getConstPointer();
2913 const int *ci=_nodal_connec_index->getConstPointer();
2914 for(int i=0;i<nbOfCells;i++)
2916 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
2917 stream << "Cell #" << i << " " << cm.getRepr() << " : ";
2918 std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
2923 stream << "Connectivity not defined !\n";
2926 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
2928 const int *ptI=_nodal_connec_index->getConstPointer();
2929 const int *pt=_nodal_connec->getConstPointer();
2930 if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
2931 return ptI[cellId+1]-ptI[cellId]-1;
2933 return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
2937 * Returns types of cells of the specified part of \a this mesh.
2938 * This method avoids computing sub-mesh explicitely to get its types.
2939 * \param [in] begin - an array of cell ids of interest.
2940 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
2941 * \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
2942 * describing the cell types.
2943 * \throw If the coordinates array is not set.
2944 * \throw If the nodal connectivity of cells is not defined.
2945 * \sa getAllGeoTypes()
2947 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
2949 checkFullyDefined();
2950 std::set<INTERP_KERNEL::NormalizedCellType> ret;
2951 const int *conn=_nodal_connec->getConstPointer();
2952 const int *connIndex=_nodal_connec_index->getConstPointer();
2953 for(const int *w=begin;w!=end;w++)
2954 ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
2959 * Defines the nodal connectivity using given connectivity arrays. Optionally updates
2960 * a set of types of cells constituting \a this mesh.
2961 * This method is for advanced users having prepared their connectivity before. For
2962 * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
2963 * \param [in] conn - the nodal connectivity array.
2964 * \param [in] connIndex - the nodal connectivity index array.
2965 * \param [in] isComputingTypes - if \c true, the set of types constituting \a this
2968 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
2970 DataArrayInt::SetArrayIn(conn,_nodal_connec);
2971 DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
2972 if(isComputingTypes)
2978 * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
2979 * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
2981 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
2982 _nodal_connec(0),_nodal_connec_index(0),
2983 _types(other._types)
2985 if(other._nodal_connec)
2986 _nodal_connec=other._nodal_connec->performCpy(deepCopy);
2987 if(other._nodal_connec_index)
2988 _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
2991 MEDCouplingUMesh::~MEDCouplingUMesh()
2994 _nodal_connec->decrRef();
2995 if(_nodal_connec_index)
2996 _nodal_connec_index->decrRef();
3000 * Recomputes a set of cell types of \a this mesh. For more info see
3001 * \ref MEDCouplingUMeshNodalConnectivity.
3003 void MEDCouplingUMesh::computeTypes()
3005 if(_nodal_connec && _nodal_connec_index)
3008 const int *conn=_nodal_connec->getConstPointer();
3009 const int *connIndex=_nodal_connec_index->getConstPointer();
3010 int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
3012 for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
3013 _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
3018 * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3020 void MEDCouplingUMesh::checkFullyDefined() const
3022 if(!_nodal_connec_index || !_nodal_connec || !_coords)
3023 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3027 * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3029 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3031 if(!_nodal_connec_index || !_nodal_connec)
3032 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3036 * Returns a number of cells constituting \a this mesh.
3037 * \return int - the number of cells in \a this mesh.
3038 * \throw If the nodal connectivity of cells is not defined.
3040 int MEDCouplingUMesh::getNumberOfCells() const
3042 if(_nodal_connec_index)
3043 return _nodal_connec_index->getNumberOfTuples()-1;
3048 throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3052 * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3053 * mesh. For more info see \ref MEDCouplingMeshesPage.
3054 * \return int - the dimension of \a this mesh.
3055 * \throw If the mesh dimension is not defined using setMeshDimension().
3057 int MEDCouplingUMesh::getMeshDimension() const
3060 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3065 * Returns a length of the nodal connectivity array.
3066 * This method is for test reason. Normally the integer returned is not useable by
3067 * user. For more info see \ref MEDCouplingUMeshNodalConnectivity.
3068 * \return int - the length of the nodal connectivity array.
3070 int MEDCouplingUMesh::getMeshLength() const
3072 return _nodal_connec->getNbOfElems();
3076 * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3078 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3080 MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3081 tinyInfo.push_back(getMeshDimension());
3082 tinyInfo.push_back(getNumberOfCells());
3084 tinyInfo.push_back(getMeshLength());
3086 tinyInfo.push_back(-1);
3090 * First step of unserialization process.
3092 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3094 return tinyInfo[6]<=0;
3098 * Second step of serialization process.
3099 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3101 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3103 MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3105 a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3109 * Third and final step of serialization process.
3111 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3113 MEDCouplingPointSet::serialize(a1,a2);
3114 if(getMeshDimension()>-1)
3116 a1=DataArrayInt::New();
3117 a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3118 int *ptA1=a1->getPointer();
3119 const int *conn=getNodalConnectivity()->getConstPointer();
3120 const int *index=getNodalConnectivityIndex()->getConstPointer();
3121 ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3122 std::copy(conn,conn+getMeshLength(),ptA1);
3129 * Second and final unserialization process.
3130 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3132 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3134 MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3135 setMeshDimension(tinyInfo[5]);
3139 const int *recvBuffer=a1->getConstPointer();
3140 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3141 myConnecIndex->alloc(tinyInfo[6]+1,1);
3142 std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3143 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3144 myConnec->alloc(tinyInfo[7],1);
3145 std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3146 setConnectivity(myConnec, myConnecIndex);
3151 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3152 * CellIds are given using range specified by a start an end and step.
3154 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3156 checkFullyDefined();
3157 int ncell=getNumberOfCells();
3158 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3159 ret->_mesh_dim=_mesh_dim;
3160 ret->setCoords(_coords);
3161 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3162 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3163 int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3165 const int *conn=_nodal_connec->getConstPointer();
3166 const int *connIndex=_nodal_connec_index->getConstPointer();
3167 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3169 if(work>=0 && work<ncell)
3171 newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3175 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3176 throw INTERP_KERNEL::Exception(oss.str().c_str());
3179 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3180 int *newConnPtr=newConn->getPointer();
3181 std::set<INTERP_KERNEL::NormalizedCellType> types;
3183 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3185 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3186 newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3188 ret->setConnectivity(newConn,newConnI,false);
3190 ret->copyTinyInfoFrom(this);
3195 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3196 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3197 * The return newly allocated mesh will share the same coordinates as \a this.
3199 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3201 checkConnectivityFullyDefined();
3202 int ncell=getNumberOfCells();
3203 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3204 ret->_mesh_dim=_mesh_dim;
3205 ret->setCoords(_coords);
3206 std::size_t nbOfElemsRet=std::distance(begin,end);
3207 int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3209 const int *conn=_nodal_connec->getConstPointer();
3210 const int *connIndex=_nodal_connec_index->getConstPointer();
3212 for(const int *work=begin;work!=end;work++,newNbring++)
3214 if(*work>=0 && *work<ncell)
3215 connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3219 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3220 throw INTERP_KERNEL::Exception(oss.str().c_str());
3223 int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3224 int *connRetWork=connRet;
3225 std::set<INTERP_KERNEL::NormalizedCellType> types;
3226 for(const int *work=begin;work!=end;work++)
3228 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3229 connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3231 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3232 connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3233 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3234 connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3235 ret->setConnectivity(connRetArr,connIndexRetArr,false);
3237 ret->copyTinyInfoFrom(this);
3242 * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3244 * For 1D cells, the returned field contains lengths.<br>
3245 * For 2D cells, the returned field contains areas.<br>
3246 * For 3D cells, the returned field contains volumes.
3247 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3248 * orientation, i.e. the volume is always positive.
3249 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3250 * and one time . The caller is to delete this field using decrRef() as it is no
3253 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3255 std::string name="MeasureOfMesh_";
3257 int nbelem=getNumberOfCells();
3258 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3259 field->setName(name);
3260 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3261 array->alloc(nbelem,1);
3262 double *area_vol=array->getPointer();
3263 field->setArray(array) ; array=0;
3264 field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3265 field->synchronizeTimeWithMesh();
3266 if(getMeshDimension()!=-1)
3269 INTERP_KERNEL::NormalizedCellType type;
3270 int dim_space=getSpaceDimension();
3271 const double *coords=getCoords()->getConstPointer();
3272 const int *connec=getNodalConnectivity()->getConstPointer();
3273 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3274 for(int iel=0;iel<nbelem;iel++)
3276 ipt=connec_index[iel];
3277 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3278 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);
3281 std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3285 area_vol[0]=std::numeric_limits<double>::max();
3287 return field.retn();
3291 * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3293 * For 1D cells, the returned array contains lengths.<br>
3294 * For 2D cells, the returned array contains areas.<br>
3295 * For 3D cells, the returned array contains volumes.
3296 * This method avoids building explicitly a part of \a this mesh to perform the work.
3297 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3298 * orientation, i.e. the volume is always positive.
3299 * \param [in] begin - an array of cell ids of interest.
3300 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3301 * \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3302 * delete this array using decrRef() as it is no more needed.
3304 * \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3305 * \ref py_mcumesh_getPartMeasureField "Here is a Python example".
3306 * \sa getMeasureField()
3308 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3310 std::string name="PartMeasureOfMesh_";
3312 int nbelem=(int)std::distance(begin,end);
3313 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3314 array->setName(name);
3315 array->alloc(nbelem,1);
3316 double *area_vol=array->getPointer();
3317 if(getMeshDimension()!=-1)
3320 INTERP_KERNEL::NormalizedCellType type;
3321 int dim_space=getSpaceDimension();
3322 const double *coords=getCoords()->getConstPointer();
3323 const int *connec=getNodalConnectivity()->getConstPointer();
3324 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3325 for(const int *iel=begin;iel!=end;iel++)
3327 ipt=connec_index[*iel];
3328 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3329 *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3332 std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3336 area_vol[0]=std::numeric_limits<double>::max();
3338 return array.retn();
3342 * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3343 * \a this one. The returned field contains the dual cell volume for each corresponding
3344 * node in \a this mesh. In other words, the field returns the getMeasureField() of
3345 * the dual mesh in P1 sens of \a this.<br>
3346 * For 1D cells, the returned field contains lengths.<br>
3347 * For 2D cells, the returned field contains areas.<br>
3348 * For 3D cells, the returned field contains volumes.
3349 * This method is useful to check "P1*" conservative interpolators.
3350 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3351 * orientation, i.e. the volume is always positive.
3352 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3353 * nodes and one time. The caller is to delete this array using decrRef() as
3354 * it is no more needed.
3356 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3358 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3359 std::string name="MeasureOnNodeOfMesh_";
3361 int nbNodes=getNumberOfNodes();
3362 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3363 double cst=1./((double)getMeshDimension()+1.);
3364 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3365 array->alloc(nbNodes,1);
3366 double *valsToFill=array->getPointer();
3367 std::fill(valsToFill,valsToFill+nbNodes,0.);
3368 const double *values=tmp->getArray()->getConstPointer();
3369 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3370 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3371 getReverseNodalConnectivity(da,daInd);
3372 const int *daPtr=da->getConstPointer();
3373 const int *daIPtr=daInd->getConstPointer();
3374 for(int i=0;i<nbNodes;i++)
3375 for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3376 valsToFill[i]+=cst*values[*cell];
3378 ret->setArray(array);
3383 * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3384 * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3385 * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3386 * and are normalized.
3387 * <br> \a this can be either
3388 * - a 2D mesh in 2D or 3D space or
3389 * - an 1D mesh in 2D space.
3391 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3392 * cells and one time. The caller is to delete this field using decrRef() as
3393 * it is no more needed.
3394 * \throw If the nodal connectivity of cells is not defined.
3395 * \throw If the coordinates array is not set.
3396 * \throw If the mesh dimension is not set.
3397 * \throw If the mesh and space dimension is not as specified above.
3399 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3401 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3402 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3403 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3404 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3405 int nbOfCells=getNumberOfCells();
3406 int nbComp=getMeshDimension()+1;
3407 array->alloc(nbOfCells,nbComp);
3408 double *vals=array->getPointer();
3409 const int *connI=_nodal_connec_index->getConstPointer();
3410 const int *conn=_nodal_connec->getConstPointer();
3411 const double *coords=_coords->getConstPointer();
3412 if(getMeshDimension()==2)
3414 if(getSpaceDimension()==3)
3416 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3417 const double *locPtr=loc->getConstPointer();
3418 for(int i=0;i<nbOfCells;i++,vals+=3)
3420 int offset=connI[i];
3421 INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3422 double n=INTERP_KERNEL::norm<3>(vals);
3423 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3428 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3429 const double *isAbsPtr=isAbs->getArray()->begin();
3430 for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3431 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3434 else//meshdimension==1
3437 for(int i=0;i<nbOfCells;i++)
3439 int offset=connI[i];
3440 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3441 double n=INTERP_KERNEL::norm<2>(tmp);
3442 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3447 ret->setArray(array);
3449 ret->synchronizeTimeWithSupport();
3454 * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3455 * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3456 * and are normalized.
3457 * <br> \a this can be either
3458 * - a 2D mesh in 2D or 3D space or
3459 * - an 1D mesh in 2D space.
3461 * This method avoids building explicitly a part of \a this mesh to perform the work.
3462 * \param [in] begin - an array of cell ids of interest.
3463 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3464 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3465 * cells and one time. The caller is to delete this field using decrRef() as
3466 * it is no more needed.
3467 * \throw If the nodal connectivity of cells is not defined.
3468 * \throw If the coordinates array is not set.
3469 * \throw If the mesh dimension is not set.
3470 * \throw If the mesh and space dimension is not as specified above.
3471 * \sa buildOrthogonalField()
3473 * \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3474 * \ref py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3476 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3478 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3479 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3480 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3481 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3482 std::size_t nbelems=std::distance(begin,end);
3483 int nbComp=getMeshDimension()+1;
3484 array->alloc((int)nbelems,nbComp);
3485 double *vals=array->getPointer();
3486 const int *connI=_nodal_connec_index->getConstPointer();
3487 const int *conn=_nodal_connec->getConstPointer();
3488 const double *coords=_coords->getConstPointer();
3489 if(getMeshDimension()==2)
3491 if(getSpaceDimension()==3)
3493 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3494 const double *locPtr=loc->getConstPointer();
3495 for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3497 int offset=connI[*i];
3498 INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3499 double n=INTERP_KERNEL::norm<3>(vals);
3500 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3505 for(std::size_t i=0;i<nbelems;i++)
3506 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3509 else//meshdimension==1
3512 for(const int *i=begin;i!=end;i++)
3514 int offset=connI[*i];
3515 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3516 double n=INTERP_KERNEL::norm<2>(tmp);
3517 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3522 ret->setArray(array);
3524 ret->synchronizeTimeWithSupport();
3529 * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3530 * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3531 * and are \b not normalized.
3532 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3533 * cells and one time. The caller is to delete this field using decrRef() as
3534 * it is no more needed.
3535 * \throw If the nodal connectivity of cells is not defined.
3536 * \throw If the coordinates array is not set.
3537 * \throw If \a this->getMeshDimension() != 1.
3538 * \throw If \a this mesh includes cells of type other than SEG2.
3540 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3542 if(getMeshDimension()!=1)
3543 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3544 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3545 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3546 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3547 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3548 int nbOfCells=getNumberOfCells();
3549 int spaceDim=getSpaceDimension();
3550 array->alloc(nbOfCells,spaceDim);
3551 double *pt=array->getPointer();
3552 const double *coo=getCoords()->getConstPointer();
3553 std::vector<int> conn;
3555 for(int i=0;i<nbOfCells;i++)
3558 getNodeIdsOfCell(i,conn);
3559 pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3561 ret->setArray(array);
3563 ret->synchronizeTimeWithSupport();
3568 * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3569 * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3570 * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3571 * from. If a result face is shared by two 3D cells, then the face in included twice in
3573 * \param [in] origin - 3 components of a point defining location of the plane.
3574 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3575 * must be greater than 1e-6.
3576 * \param [in] eps - half-thickness of the plane.
3577 * \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3578 * producing correspondent 2D cells. The caller is to delete this array
3579 * using decrRef() as it is no more needed.
3580 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3581 * not share the node coordinates array with \a this mesh. The caller is to
3582 * delete this mesh using decrRef() as it is no more needed.
3583 * \throw If the coordinates array is not set.
3584 * \throw If the nodal connectivity of cells is not defined.
3585 * \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3586 * \throw If magnitude of \a vec is less than 1e-6.
3587 * \throw If the plane does not intersect any 3D cell of \a this mesh.
3588 * \throw If \a this includes quadratic cells.
3590 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3592 checkFullyDefined();
3593 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3594 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3595 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3596 if(candidates->empty())
3597 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3598 std::vector<int> nodes;
3599 DataArrayInt *cellIds1D=0;
3600 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3601 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3602 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3603 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3604 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3605 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3606 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3607 revDesc2=0; revDescIndx2=0;
3608 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3609 revDesc1=0; revDescIndx1=0;
3610 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3611 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3613 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3614 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3616 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3617 std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3618 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3619 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3620 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3621 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3622 connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3623 subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3624 if(cellIds2->empty())
3625 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3626 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3627 ret->setCoords(mDesc1->getCoords());
3628 ret->setConnectivity(conn,connI,true);
3629 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3634 * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3635 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
3636 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3638 * \param [in] origin - 3 components of a point defining location of the plane.
3639 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3640 * must be greater than 1e-6.
3641 * \param [in] eps - half-thickness of the plane.
3642 * \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3643 * producing correspondent segments. The caller is to delete this array
3644 * using decrRef() as it is no more needed.
3645 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3646 * mesh in 3D space. This mesh does not share the node coordinates array with
3647 * \a this mesh. The caller is to delete this mesh using decrRef() as it is
3649 * \throw If the coordinates array is not set.
3650 * \throw If the nodal connectivity of cells is not defined.
3651 * \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3652 * \throw If magnitude of \a vec is less than 1e-6.
3653 * \throw If the plane does not intersect any 2D cell of \a this mesh.
3654 * \throw If \a this includes quadratic cells.
3656 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3658 checkFullyDefined();
3659 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3660 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3661 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3662 if(candidates->empty())
3663 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3664 std::vector<int> nodes;
3665 DataArrayInt *cellIds1D=0;
3666 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3667 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3668 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3669 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3670 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3671 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3672 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3673 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3674 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3676 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3677 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3679 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3680 int ncellsSub=subMesh->getNumberOfCells();
3681 std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3682 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3683 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3684 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3685 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3687 const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3688 const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3689 for(int i=0;i<ncellsSub;i++)
3691 if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3693 if(cut3DSurf[i].first!=-2)
3695 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3696 connI->pushBackSilent(conn->getNumberOfTuples());
3697 cellIds2->pushBackSilent(i);
3701 int cellId3DSurf=cut3DSurf[i].second;
3702 int offset=nodalI[cellId3DSurf]+1;
3703 int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3704 for(int j=0;j<nbOfEdges;j++)
3706 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3707 connI->pushBackSilent(conn->getNumberOfTuples());
3708 cellIds2->pushBackSilent(cellId3DSurf);
3713 if(cellIds2->empty())
3714 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3715 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3716 ret->setCoords(mDesc1->getCoords());
3717 ret->setConnectivity(conn,connI,true);
3718 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3723 * Finds cells whose bounding boxes intersect a given plane.
3724 * \param [in] origin - 3 components of a point defining location of the plane.
3725 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3726 * must be greater than 1e-6.
3727 * \param [in] eps - half-thickness of the plane.
3728 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3729 * cells. The caller is to delete this array using decrRef() as it is no more
3731 * \throw If the coordinates array is not set.
3732 * \throw If the nodal connectivity of cells is not defined.
3733 * \throw If \a this->getSpaceDimension() != 3.
3734 * \throw If magnitude of \a vec is less than 1e-6.
3735 * \sa buildSlice3D()
3737 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3739 checkFullyDefined();
3740 if(getSpaceDimension()!=3)
3741 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3742 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3744 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3746 vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3747 double angle=acos(vec[2]/normm);
3748 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3752 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3753 MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3754 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3756 mw->getBoundingBox(bbox);
3757 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3758 cellIds=mw->getCellsInBoundingBox(bbox,eps);
3762 getBoundingBox(bbox);
3763 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3764 cellIds=getCellsInBoundingBox(bbox,eps);
3766 return cellIds.retn();
3770 * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3771 * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3772 * No consideration of coordinate is done by this method.
3773 * 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)
3774 * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3776 bool MEDCouplingUMesh::isContiguous1D() const
3778 if(getMeshDimension()!=1)
3779 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3780 int nbCells=getNumberOfCells();
3782 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3783 const int *connI=_nodal_connec_index->getConstPointer();
3784 const int *conn=_nodal_connec->getConstPointer();
3785 int ref=conn[connI[0]+2];
3786 for(int i=1;i<nbCells;i++)
3788 if(conn[connI[i]+1]!=ref)
3790 ref=conn[connI[i]+2];
3796 * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3797 * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3798 * \param pt reference point of the line
3799 * \param v normalized director vector of the line
3800 * \param eps max precision before throwing an exception
3801 * \param res output of size this->getNumberOfCells
3803 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3805 if(getMeshDimension()!=1)
3806 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3807 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3808 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3809 if(getSpaceDimension()!=3)
3810 throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3811 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3812 const double *fPtr=f->getArray()->getConstPointer();
3814 for(int i=0;i<getNumberOfCells();i++)
3816 const double *tmp1=fPtr+3*i;
3817 tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3818 tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3819 tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3820 double n1=INTERP_KERNEL::norm<3>(tmp);
3821 n1/=INTERP_KERNEL::norm<3>(tmp1);
3823 throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3825 const double *coo=getCoords()->getConstPointer();
3826 for(int i=0;i<getNumberOfNodes();i++)
3828 std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3829 std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3830 res[i]=std::accumulate(tmp,tmp+3,0.);
3835 * 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.
3836 * \a this is expected to be a mesh so that its space dimension is equal to its
3837 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3838 * 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).
3840 * 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
3841 * 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).
3842 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3844 * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3845 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3847 * \param [in] ptBg the start pointer (included) of the coordinates of the point
3848 * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3849 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3850 * \return the positive value of the distance.
3851 * \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
3853 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3855 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
3857 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3858 if(meshDim!=spaceDim-1)
3859 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3860 if(meshDim!=2 && meshDim!=1)
3861 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3862 checkFullyDefined();
3863 if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3864 { 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()); }
3865 DataArrayInt *ret1=0;
3866 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
3867 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
3868 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
3869 cellId=*ret1Safe->begin();
3870 return *ret0->begin();
3874 * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
3875 * to \a this and the first \a cellId in \a this corresponding to the returned distance.
3876 * 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
3877 * 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).
3878 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3880 * \a this is expected to be a mesh so that its space dimension is equal to its
3881 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3882 * 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).
3884 * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
3885 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3887 * \param [in] pts the list of points in which each tuple represents a point
3888 * \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.
3889 * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
3890 * \throw if number of components of \a pts is not equal to the space dimension.
3891 * \throw if mesh dimension of \a this is not equal to space dimension - 1.
3892 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
3894 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
3897 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
3898 pts->checkAllocated();
3899 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3900 if(meshDim!=spaceDim-1)
3901 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
3902 if(meshDim!=2 && meshDim!=1)
3903 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
3904 if(pts->getNumberOfComponents()!=spaceDim)
3906 std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
3907 throw INTERP_KERNEL::Exception(oss.str().c_str());
3909 checkFullyDefined();
3910 int nbCells=getNumberOfCells();
3912 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
3913 int nbOfPts=pts->getNumberOfTuples();
3914 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
3915 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
3916 const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
3917 double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
3918 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
3919 const double *bbox(bboxArr->begin());
3924 BBTreeDst<3> myTree(bbox,0,0,nbCells);
3925 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
3927 double x=std::numeric_limits<double>::max();
3928 std::vector<int> elems;
3929 myTree.getMinDistanceOfMax(ptsPtr,x);
3930 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3931 DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3937 BBTreeDst<2> myTree(bbox,0,0,nbCells);
3938 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
3940 double x=std::numeric_limits<double>::max();
3941 std::vector<int> elems;
3942 myTree.getMinDistanceOfMax(ptsPtr,x);
3943 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3944 DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3949 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
3951 cellIds=ret1.retn();
3956 * \param [in] pt the start pointer (included) of the coordinates of the point
3957 * \param [in] cellIdsBg the start pointer (included) of cellIds
3958 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3959 * \param [in] nc nodal connectivity
3960 * \param [in] ncI nodal connectivity index
3961 * \param [in,out] ret0 the min distance between \a this and the external input point
3962 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3963 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
3965 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)
3968 ret0=std::numeric_limits<double>::max();
3969 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
3971 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
3973 case INTERP_KERNEL::NORM_TRI3:
3975 double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
3977 { ret0=tmp; cellId=*zeCell; }
3980 case INTERP_KERNEL::NORM_QUAD4:
3981 case INTERP_KERNEL::NORM_POLYGON:
3983 double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
3985 { ret0=tmp; cellId=*zeCell; }
3989 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
3995 * \param [in] pt the start pointer (included) of the coordinates of the point
3996 * \param [in] cellIdsBg the start pointer (included) of cellIds
3997 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3998 * \param [in] nc nodal connectivity
3999 * \param [in] ncI nodal connectivity index
4000 * \param [in,out] ret0 the min distance between \a this and the external input point
4001 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4002 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4004 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)
4007 ret0=std::numeric_limits<double>::max();
4008 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4010 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4012 case INTERP_KERNEL::NORM_SEG2:
4014 std::size_t uselessEntry=0;
4015 double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4018 { ret0=tmp; cellId=*zeCell; }
4022 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4028 * Finds cells in contact with a ball (i.e. a point with precision).
4029 * 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.
4030 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4032 * \warning This method is suitable if the caller intends to evaluate only one
4033 * point, for more points getCellsContainingPoints() is recommended as it is
4035 * \param [in] pos - array of coordinates of the ball central point.
4036 * \param [in] eps - ball radius.
4037 * \return int - a smallest id of cells being in contact with the ball, -1 in case
4038 * if there are no such cells.
4039 * \throw If the coordinates array is not set.
4040 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4042 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4044 std::vector<int> elts;
4045 getCellsContainingPoint(pos,eps,elts);
4048 return elts.front();
4052 * Finds cells in contact with a ball (i.e. a point with precision).
4053 * 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.
4054 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4055 * \warning This method is suitable if the caller intends to evaluate only one
4056 * point, for more points getCellsContainingPoints() is recommended as it is
4058 * \param [in] pos - array of coordinates of the ball central point.
4059 * \param [in] eps - ball radius.
4060 * \param [out] elts - vector returning ids of the found cells. It is cleared
4061 * before inserting ids.
4062 * \throw If the coordinates array is not set.
4063 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4065 * \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4066 * \ref py_mcumesh_getCellsContainingPoint "Here is a Python example".
4068 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4070 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4071 getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4072 elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4077 namespace ParaMEDMEM
4079 template<const int SPACEDIMM>
4083 static const int MY_SPACEDIM=SPACEDIMM;
4084 static const int MY_MESHDIM=8;
4085 typedef int MyConnType;
4086 static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4088 // useless, but for windows compilation ...
4089 const double* getCoordinatesPtr() const { return 0; }
4090 const int* getConnectivityPtr() const { return 0; }
4091 const int* getConnectivityIndexPtr() const { return 0; }
4092 INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4096 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4098 INTERP_KERNEL::Edge *ret=0;
4101 case INTERP_KERNEL::NORM_SEG2:
4103 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4106 case INTERP_KERNEL::NORM_SEG3:
4108 INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4109 INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4110 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4111 // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4112 bool colinearity=inters.areColinears();
4113 delete e1; delete e2;
4115 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4117 ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4118 mapp2[bg[2]].second=false;
4122 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4128 * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4129 * the global mesh 'mDesc'.
4130 * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4131 * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4133 INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4134 std::map<INTERP_KERNEL::Node *,int>& mapp)
4135 throw(INTERP_KERNEL::Exception)
4138 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.
4139 const double *coo=mDesc->getCoords()->getConstPointer();
4140 const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4141 const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4143 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4144 s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4145 for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4147 INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4148 mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4150 INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4151 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4153 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4154 ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4156 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4158 if((*it2).second.second)
4159 mapp[(*it2).second.first]=(*it2).first;
4160 ((*it2).second.first)->decrRef();
4165 INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4169 int locId=nodeId-offset2;
4170 return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4174 int locId=nodeId-offset1;
4175 return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4177 return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4181 * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4183 void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4184 const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4185 /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4187 for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4189 int eltId1=abs(*desc1)-1;
4190 for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4192 std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4193 if(it==mappRev.end())
4195 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4206 template<int SPACEDIM>
4207 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4208 double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4210 elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4211 int *eltsIndexPtr(eltsIndex->getPointer());
4212 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4213 const double *bbox(bboxArr->begin());
4214 int nbOfCells=getNumberOfCells();
4215 const int *conn=_nodal_connec->getConstPointer();
4216 const int *connI=_nodal_connec_index->getConstPointer();
4217 double bb[2*SPACEDIM];
4218 BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4219 for(int i=0;i<nbOfPoints;i++)
4221 eltsIndexPtr[i+1]=eltsIndexPtr[i];
4222 for(int j=0;j<SPACEDIM;j++)
4224 bb[2*j]=pos[SPACEDIM*i+j];
4225 bb[2*j+1]=pos[SPACEDIM*i+j];
4227 std::vector<int> candidates;
4228 myTree.getIntersectingElems(bb,candidates);
4229 for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4231 int sz(connI[(*iter)+1]-connI[*iter]-1);
4232 INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4234 if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4235 status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4239 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4240 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4241 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4242 std::vector<INTERP_KERNEL::Node *> nodes(sz);
4243 INTERP_KERNEL::QuadraticPolygon *pol(0);
4244 for(int j=0;j<sz;j++)
4246 int nodeId(conn[connI[*iter]+1+j]);
4247 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4249 if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4250 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4252 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4253 INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4254 double a(0.),b(0.),c(0.);
4255 a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4256 status=pol->isInOrOut2(n);
4257 delete pol; n->decrRef();
4261 eltsIndexPtr[i+1]++;
4262 elts->pushBackSilent(*iter);
4268 * Finds cells in contact with several balls (i.e. points with precision).
4269 * This method is an extension of getCellContainingPoint() and
4270 * getCellsContainingPoint() for the case of multiple points.
4271 * 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.
4272 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4273 * \param [in] pos - an array of coordinates of points in full interlace mode :
4274 * X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4275 * this->getSpaceDimension() * \a nbOfPoints
4276 * \param [in] nbOfPoints - number of points to locate within \a this mesh.
4277 * \param [in] eps - radius of balls (i.e. the precision).
4278 * \param [out] elts - vector returning ids of found cells.
4279 * \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4280 * dividing cell ids in \a elts into groups each referring to one
4281 * point. Its every element (except the last one) is an index pointing to the
4282 * first id of a group of cells. For example cells in contact with the *i*-th
4283 * point are described by following range of indices:
4284 * [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4285 * \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4286 * Number of cells in contact with the *i*-th point is
4287 * \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4288 * \throw If the coordinates array is not set.
4289 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4291 * \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4292 * \ref py_mcumesh_getCellsContainingPoints "Here is a Python example".
4294 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4295 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4297 int spaceDim=getSpaceDimension();
4298 int mDim=getMeshDimension();
4303 const double *coords=_coords->getConstPointer();
4304 getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4311 throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4313 else if(spaceDim==2)
4317 const double *coords=_coords->getConstPointer();
4318 getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4321 throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4323 else if(spaceDim==1)
4327 const double *coords=_coords->getConstPointer();
4328 getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4331 throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4334 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4338 * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4339 * least two its edges intersect each other anywhere except their extremities. An
4340 * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4341 * \param [in,out] cells - a vector returning ids of the found cells. It is not
4342 * cleared before filling in.
4343 * \param [in] eps - precision.
4344 * \throw If \a this->getMeshDimension() != 2.
4345 * \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4347 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4349 const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4350 if(getMeshDimension()!=2)
4351 throw INTERP_KERNEL::Exception(msg);
4352 int spaceDim=getSpaceDimension();
4353 if(spaceDim!=2 && spaceDim!=3)
4354 throw INTERP_KERNEL::Exception(msg);
4355 const int *conn=_nodal_connec->getConstPointer();
4356 const int *connI=_nodal_connec_index->getConstPointer();
4357 int nbOfCells=getNumberOfCells();
4358 std::vector<double> cell2DinS2;
4359 for(int i=0;i<nbOfCells;i++)
4361 int offset=connI[i];
4362 int nbOfNodesForCell=connI[i+1]-offset-1;
4363 if(nbOfNodesForCell<=3)
4365 bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4366 project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4367 if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4374 * This method is typically requested to unbutterfly 2D linear cells in \b this.
4376 * 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.
4377 * 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.
4379 * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4380 * This convex envelop is computed using Jarvis march algorithm.
4381 * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4382 * 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)
4383 * 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.
4385 * \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.
4387 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4389 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4390 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D works only for meshDim=2 and spaceDim=2 !");
4391 checkFullyDefined();
4392 const double *coords=getCoords()->getConstPointer();
4393 int nbOfCells=getNumberOfCells();
4394 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4395 nodalConnecIndexOut->alloc(nbOfCells+1,1);
4396 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4397 int *workIndexOut=nodalConnecIndexOut->getPointer();
4399 const int *nodalConnecIn=_nodal_connec->getConstPointer();
4400 const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4401 std::set<INTERP_KERNEL::NormalizedCellType> types;
4402 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4403 isChanged->alloc(0,1);
4404 for(int i=0;i<nbOfCells;i++,workIndexOut++)
4406 int pos=nodalConnecOut->getNumberOfTuples();
4407 if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4408 isChanged->pushBackSilent(i);
4409 types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4410 workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4412 if(isChanged->empty())
4414 setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4416 return isChanged.retn();
4420 * This method is \b NOT const because it can modify \a this.
4421 * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4422 * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4423 * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4424 * \b 1 for translation and rotation around point of 'mesh1D'.
4425 * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.
4427 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4429 checkFullyDefined();
4430 mesh1D->checkFullyDefined();
4431 if(!mesh1D->isContiguous1D())
4432 throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4433 if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4434 throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4435 if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4436 throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4437 if(mesh1D->getMeshDimension()!=1)
4438 throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4440 if(isPresenceOfQuadratic())
4442 if(mesh1D->isFullyQuadratic())
4445 throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4448 int oldNbOfNodes=getNumberOfNodes();
4449 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4454 newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4459 newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4463 throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4465 setCoords(newCoords);
4466 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4472 * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4473 * If it is not the case an exception will be thrown.
4474 * This method is non const because the coordinate of \a this can be appended with some new points issued from
4475 * intersection of plane defined by ('origin','vec').
4476 * This method has one in/out parameter : 'cut3DCurve'.
4477 * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4478 * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4479 * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4480 * This method will throw an exception if \a this contains a non linear segment.
4482 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4484 checkFullyDefined();
4485 if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4486 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4487 int ncells=getNumberOfCells();
4488 int nnodes=getNumberOfNodes();
4489 double vec2[3],vec3[3],vec4[3];
4490 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4492 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4493 vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4494 const int *conn=_nodal_connec->getConstPointer();
4495 const int *connI=_nodal_connec_index->getConstPointer();
4496 const double *coo=_coords->getConstPointer();
4497 std::vector<double> addCoo;
4498 for(int i=0;i<ncells;i++)
4500 if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4502 if(cut3DCurve[i]==-2)
4504 int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4505 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];
4506 double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4507 double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4508 if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4510 const double *st2=coo+3*st;
4511 vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4512 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]));
4513 if(pos>eps && pos<1-eps)
4515 int nNode=((int)addCoo.size())/3;
4516 vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4517 addCoo.insert(addCoo.end(),vec4,vec4+3);
4518 cut3DCurve[i]=nnodes+nNode;
4524 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4528 int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4529 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4530 coo2->alloc(newNbOfNodes,3);
4531 double *tmp=coo2->getPointer();
4532 tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4533 std::copy(addCoo.begin(),addCoo.end(),tmp);
4534 DataArrayDouble::SetArrayIn(coo2,_coords);
4539 * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4540 * \param mesh1D is the input 1D mesh used for translation computation.
4541 * \return newCoords new coords filled by this method.
4543 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4545 int oldNbOfNodes=getNumberOfNodes();
4546 int nbOf1DCells=mesh1D->getNumberOfCells();
4547 int spaceDim=getSpaceDimension();
4548 DataArrayDouble *ret=DataArrayDouble::New();
4549 std::vector<bool> isQuads;
4550 int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4551 ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4552 double *retPtr=ret->getPointer();
4553 const double *coords=getCoords()->getConstPointer();
4554 double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4556 std::vector<double> c;
4560 for(int i=0;i<nbOf1DCells;i++)
4563 mesh1D->getNodeIdsOfCell(i,v);
4565 mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4566 mesh1D->getCoordinatesOfNode(v[0],c);
4567 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4568 for(int j=0;j<oldNbOfNodes;j++)
4569 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4573 mesh1D->getCoordinatesOfNode(v[1],c);
4574 mesh1D->getCoordinatesOfNode(v[0],c);
4575 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4576 for(int j=0;j<oldNbOfNodes;j++)
4577 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4580 ret->copyStringInfoFrom(*getCoords());
4585 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4586 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4587 * \return newCoords new coords filled by this method.
4589 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4591 if(mesh1D->getSpaceDimension()==2)
4592 return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4593 if(mesh1D->getSpaceDimension()==3)
4594 return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4595 throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4599 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4600 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4601 * \return newCoords new coords filled by this method.
4603 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4606 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4607 int oldNbOfNodes=getNumberOfNodes();
4608 int nbOf1DCells=mesh1D->getNumberOfCells();
4610 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4611 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4612 int nbOfLevsInVec=nbOf1DCells+1;
4613 ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4614 double *retPtr=ret->getPointer();
4615 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4616 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4617 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4618 tmp->setCoords(tmp2);
4619 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4620 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4621 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4622 for(int i=1;i<nbOfLevsInVec;i++)
4624 const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4625 const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4626 const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4627 const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4628 tmp->translate(vec);
4629 double tmp3[2],radius,alpha,alpha0;
4630 const double *p0=i+1<nbOfLevsInVec?begin:third;
4631 const double *p1=i+1<nbOfLevsInVec?end:begin;
4632 const double *p2=i+1<nbOfLevsInVec?third:end;
4633 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4634 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]);
4635 double angle=acos(cosangle/(radius*radius));
4636 tmp->rotate(end,0,angle);
4637 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4643 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4644 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4645 * \return newCoords new coords filled by this method.
4647 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4650 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4651 int oldNbOfNodes=getNumberOfNodes();
4652 int nbOf1DCells=mesh1D->getNumberOfCells();
4654 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4655 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4656 int nbOfLevsInVec=nbOf1DCells+1;
4657 ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4658 double *retPtr=ret->getPointer();
4659 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4660 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4661 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4662 tmp->setCoords(tmp2);
4663 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4664 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4665 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4666 for(int i=1;i<nbOfLevsInVec;i++)
4668 const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4669 const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4670 const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4671 const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4672 tmp->translate(vec);
4673 double tmp3[2],radius,alpha,alpha0;
4674 const double *p0=i+1<nbOfLevsInVec?begin:third;
4675 const double *p1=i+1<nbOfLevsInVec?end:begin;
4676 const double *p2=i+1<nbOfLevsInVec?third:end;
4677 double vecPlane[3]={
4678 (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4679 (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4680 (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4682 double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4685 vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4686 double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4687 double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4689 double c2=cos(asin(s2));
4691 {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4692 {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4693 {-vec2[1]*s2, vec2[0]*s2, c2}
4695 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]};
4696 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]};
4697 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]};
4698 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4699 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]);
4700 double angle=acos(cosangle/(radius*radius));
4701 tmp->rotate(end,vecPlane,angle);
4704 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4710 * This method is private because not easy to use for end user. This method is const contrary to
4711 * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4712 * the coords sorted slice by slice.
4713 * \param isQuad specifies presence of quadratic cells.
4715 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4717 int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4718 int nbOf2DCells=getNumberOfCells();
4719 int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4720 MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4721 const int *conn=_nodal_connec->getConstPointer();
4722 const int *connI=_nodal_connec_index->getConstPointer();
4723 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4724 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4725 newConnI->alloc(nbOf3DCells+1,1);
4726 int *newConnIPtr=newConnI->getPointer();
4728 std::vector<int> newc;
4729 for(int j=0;j<nbOf2DCells;j++)
4731 AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4732 *newConnIPtr++=(int)newc.size();
4734 newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4735 int *newConnPtr=newConn->getPointer();
4736 int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4737 newConnIPtr=newConnI->getPointer();
4738 for(int iz=0;iz<nbOf1DCells;iz++)
4741 std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4742 for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4744 int icell=(int)(iter-newc.begin());
4745 if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4748 *newConnPtr=(*iter)+iz*deltaPerLev;
4753 *newConnPtr=(*iter);
4756 ret->setConnectivity(newConn,newConnI,true);
4757 ret->setCoords(getCoords());
4762 * Checks if \a this mesh is constituted by only quadratic cells.
4763 * \return bool - \c true if there are only quadratic cells in \a this mesh.
4764 * \throw If the coordinates array is not set.
4765 * \throw If the nodal connectivity of cells is not defined.
4767 bool MEDCouplingUMesh::isFullyQuadratic() const
4769 checkFullyDefined();
4771 int nbOfCells=getNumberOfCells();
4772 for(int i=0;i<nbOfCells && ret;i++)
4774 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4775 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4776 ret=cm.isQuadratic();
4782 * Checks if \a this mesh includes any quadratic cell.
4783 * \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4784 * \throw If the coordinates array is not set.
4785 * \throw If the nodal connectivity of cells is not defined.
4787 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4789 checkFullyDefined();
4791 int nbOfCells=getNumberOfCells();
4792 for(int i=0;i<nbOfCells && !ret;i++)
4794 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4795 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4796 ret=cm.isQuadratic();
4802 * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4803 * this mesh, it remains unchanged.
4804 * \throw If the coordinates array is not set.
4805 * \throw If the nodal connectivity of cells is not defined.
4807 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4809 checkFullyDefined();
4810 int nbOfCells=getNumberOfCells();
4812 const int *iciptr=_nodal_connec_index->getConstPointer();
4813 for(int i=0;i<nbOfCells;i++)
4815 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4816 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4817 if(cm.isQuadratic())
4819 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4820 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4821 if(!cml.isDynamic())
4822 delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4824 delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4829 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4830 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4831 const int *icptr=_nodal_connec->getConstPointer();
4832 newConn->alloc(getMeshLength()-delta,1);
4833 newConnI->alloc(nbOfCells+1,1);
4834 int *ocptr=newConn->getPointer();
4835 int *ociptr=newConnI->getPointer();
4838 for(int i=0;i<nbOfCells;i++,ociptr++)
4840 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4841 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4842 if(!cm.isQuadratic())
4844 _types.insert(type);
4845 ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4846 ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4850 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4851 _types.insert(typel);
4852 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4853 int newNbOfNodes=cml.getNumberOfNodes();
4855 newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4856 *ocptr++=(int)typel;
4857 ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4858 ociptr[1]=ociptr[0]+newNbOfNodes+1;
4861 setConnectivity(newConn,newConnI,false);
4865 * This method converts all linear cell in \a this to quadratic one.
4866 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4867 * 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)
4868 * 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.
4869 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4870 * end of the existing coordinates.
4872 * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4873 * corresponding quadratic cells. 1 is those creating the 'most' complex.
4874 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4876 * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4878 * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4880 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
4882 DataArrayInt *conn=0,*connI=0;
4883 DataArrayDouble *coords=0;
4884 std::set<INTERP_KERNEL::NormalizedCellType> types;
4885 checkFullyDefined();
4886 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
4887 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
4888 int meshDim=getMeshDimension();
4889 switch(conversionType)
4895 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4896 connSafe=conn; connISafe=connI; coordsSafe=coords;
4899 ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4900 connSafe=conn; connISafe=connI; coordsSafe=coords;
4903 ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
4904 connSafe=conn; connISafe=connI; coordsSafe=coords;
4907 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
4915 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
4916 connSafe=conn; connISafe=connI; coordsSafe=coords;
4919 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
4920 connSafe=conn; connISafe=connI; coordsSafe=coords;
4923 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
4924 connSafe=conn; connISafe=connI; coordsSafe=coords;
4927 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
4932 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
4934 setConnectivity(connSafe,connISafe,false);
4936 setCoords(coordsSafe);
4941 * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4942 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4943 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4945 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
4947 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4948 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4949 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4950 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4951 int nbOfCells=getNumberOfCells();
4952 int nbOfNodes=getNumberOfNodes();
4953 const int *cPtr=_nodal_connec->getConstPointer();
4954 const int *icPtr=_nodal_connec_index->getConstPointer();
4955 int lastVal=0,offset=nbOfNodes;
4956 for(int i=0;i<nbOfCells;i++,icPtr++)
4958 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4959 if(type==INTERP_KERNEL::NORM_SEG2)
4961 types.insert(INTERP_KERNEL::NORM_SEG3);
4962 newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
4963 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
4964 newConn->pushBackSilent(offset++);
4966 newConnI->pushBackSilent(lastVal);
4967 ret->pushBackSilent(i);
4972 lastVal+=(icPtr[1]-icPtr[0]);
4973 newConnI->pushBackSilent(lastVal);
4974 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4977 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
4978 coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
4982 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
4984 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4985 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4986 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4988 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4989 DataArrayInt *conn1D=0,*conn1DI=0;
4990 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4991 DataArrayDouble *coordsTmp=0;
4992 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4993 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4994 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4995 const int *c1DPtr=conn1D->begin();
4996 const int *c1DIPtr=conn1DI->begin();
4997 int nbOfCells=getNumberOfCells();
4998 const int *cPtr=_nodal_connec->getConstPointer();
4999 const int *icPtr=_nodal_connec_index->getConstPointer();
5001 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5003 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5004 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5005 if(!cm.isQuadratic())
5007 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5008 types.insert(typ2); newConn->pushBackSilent(typ2);
5009 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5010 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5011 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5012 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5013 newConnI->pushBackSilent(lastVal);
5014 ret->pushBackSilent(i);
5019 lastVal+=(icPtr[1]-icPtr[0]);
5020 newConnI->pushBackSilent(lastVal);
5021 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5024 conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5029 * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5030 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5031 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5033 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5036 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5037 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5038 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5041 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5043 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5044 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5046 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5047 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5048 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5050 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5051 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5052 DataArrayInt *conn1D=0,*conn1DI=0;
5053 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5054 DataArrayDouble *coordsTmp=0;
5055 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5056 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5057 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5058 const int *c1DPtr=conn1D->begin();
5059 const int *c1DIPtr=conn1DI->begin();
5060 int nbOfCells=getNumberOfCells();
5061 const int *cPtr=_nodal_connec->getConstPointer();
5062 const int *icPtr=_nodal_connec_index->getConstPointer();
5063 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5064 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5066 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5067 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5068 if(!cm.isQuadratic())
5070 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5071 types.insert(typ2); newConn->pushBackSilent(typ2);
5072 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5073 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5074 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5075 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5076 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5077 newConnI->pushBackSilent(lastVal);
5078 ret->pushBackSilent(i);
5083 lastVal+=(icPtr[1]-icPtr[0]);
5084 newConnI->pushBackSilent(lastVal);
5085 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5088 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5089 coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5094 * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5095 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5096 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5098 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5100 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5101 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5102 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5105 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5107 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5108 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5109 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5110 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5112 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5113 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5114 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5116 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5117 const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5118 DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5119 std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5120 DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5121 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5122 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5123 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5124 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5125 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5126 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5127 const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5128 int nbOfCells=getNumberOfCells();
5129 const int *cPtr=_nodal_connec->getConstPointer();
5130 const int *icPtr=_nodal_connec_index->getConstPointer();
5131 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5132 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5134 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5135 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5136 if(!cm.isQuadratic())
5138 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5139 if(typ2==INTERP_KERNEL::NORM_ERROR)
5141 std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5142 throw INTERP_KERNEL::Exception(oss.str().c_str());
5144 types.insert(typ2); newConn->pushBackSilent(typ2);
5145 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5146 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5147 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5148 for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5150 int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5151 int tmpPos=newConn->getNumberOfTuples();
5152 newConn->pushBackSilent(nodeId2);
5153 ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5155 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5156 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5157 newConnI->pushBackSilent(lastVal);
5158 ret->pushBackSilent(i);
5163 lastVal+=(icPtr[1]-icPtr[0]);
5164 newConnI->pushBackSilent(lastVal);
5165 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5168 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5169 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5170 coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5171 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5172 std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5173 int *c=newConn->getPointer();
5174 const int *cI(newConnI->begin());
5175 for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5176 c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5177 offset=coordsTmp2Safe->getNumberOfTuples();
5178 for(const int *elt=ret->begin();elt!=ret->end();elt++)
5179 c[cI[(*elt)+1]-1]+=offset;
5180 coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5185 * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5186 * so that the number of cells remains the same. Quadratic faces are converted to
5187 * polygons. This method works only for 2D meshes in
5188 * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5189 * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5190 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5191 * \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5192 * a polylinized edge constituting the input polygon.
5193 * \throw If the coordinates array is not set.
5194 * \throw If the nodal connectivity of cells is not defined.
5195 * \throw If \a this->getMeshDimension() != 2.
5196 * \throw If \a this->getSpaceDimension() != 2.
5198 void MEDCouplingUMesh::tessellate2D(double eps)
5200 checkFullyDefined();
5201 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
5202 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5203 double epsa=fabs(eps);
5204 if(epsa<std::numeric_limits<double>::min())
5205 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 !");
5206 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5207 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5208 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5209 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5210 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5211 revDesc1=0; revDescIndx1=0;
5212 mDesc->tessellate2DCurve(eps);
5213 subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5214 setCoords(mDesc->getCoords());
5218 * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5219 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5220 * \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5221 * a sub-divided edge.
5222 * \throw If the coordinates array is not set.
5223 * \throw If the nodal connectivity of cells is not defined.
5224 * \throw If \a this->getMeshDimension() != 1.
5225 * \throw If \a this->getSpaceDimension() != 2.
5227 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5229 checkFullyDefined();
5230 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5231 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5232 double epsa=fabs(eps);
5233 if(epsa<std::numeric_limits<double>::min())
5234 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 !");
5235 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5236 int nbCells=getNumberOfCells();
5237 int nbNodes=getNumberOfNodes();
5238 const int *conn=_nodal_connec->getConstPointer();
5239 const int *connI=_nodal_connec_index->getConstPointer();
5240 const double *coords=_coords->getConstPointer();
5241 std::vector<double> addCoo;
5242 std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5243 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5244 newConnI->alloc(nbCells+1,1);
5245 int *newConnIPtr=newConnI->getPointer();
5248 INTERP_KERNEL::Node *tmp2[3];
5249 std::set<INTERP_KERNEL::NormalizedCellType> types;
5250 for(int i=0;i<nbCells;i++,newConnIPtr++)
5252 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5253 if(cm.isQuadratic())
5254 {//assert(connI[i+1]-connI[i]-1==3)
5255 tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5256 tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5257 tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5258 tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5259 INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5262 eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5263 types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5265 newConnIPtr[1]=(int)newConn.size();
5269 types.insert(INTERP_KERNEL::NORM_SEG2);
5270 newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5271 newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5272 newConnIPtr[1]=newConnIPtr[0]+3;
5277 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5278 newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5279 newConnIPtr[1]=newConnIPtr[0]+3;
5282 if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5285 DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5286 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5287 newConnArr->alloc((int)newConn.size(),1);
5288 std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5289 DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5290 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5291 newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5292 double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5293 std::copy(addCoo.begin(),addCoo.end(),work);
5294 DataArrayDouble::SetArrayIn(newCoords,_coords);
5299 * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5300 * In addition, returns an array mapping new cells to old ones. <br>
5301 * This method typically increases the number of cells in \a this mesh
5302 * but the number of nodes remains \b unchanged.
5303 * That's why the 3D splitting policies
5304 * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5305 * \param [in] policy - specifies a pattern used for splitting.
5306 * The semantic of \a policy is:
5307 * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5308 * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5309 * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8 into 5 TETRA4 (for 3D mesh only).
5310 * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8 into 6 TETRA4 (for 3D mesh only).
5311 * \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5312 * an id of old cell producing it. The caller is to delete this array using
5313 * decrRef() as it is no more needed.
5314 * \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5315 * \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5316 * and \a this->getMeshDimension() != 3.
5317 * \throw If \a policy is not one of the four discussed above.
5318 * \throw If the nodal connectivity of cells is not defined.
5319 * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5321 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5326 return simplexizePol0();
5328 return simplexizePol1();
5329 case (int) INTERP_KERNEL::PLANAR_FACE_5:
5330 return simplexizePlanarFace5();
5331 case (int) INTERP_KERNEL::PLANAR_FACE_6:
5332 return simplexizePlanarFace6();
5334 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)");
5339 * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5340 * - 1D: INTERP_KERNEL::NORM_SEG2
5341 * - 2D: INTERP_KERNEL::NORM_TRI3
5342 * - 3D: INTERP_KERNEL::NORM_TETRA4.
5344 * This method is useful for users that need to use P1 field services as
5345 * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5346 * All these methods need mesh support containing only simplex cells.
5347 * \return bool - \c true if there are only simplex cells in \a this mesh.
5348 * \throw If the coordinates array is not set.
5349 * \throw If the nodal connectivity of cells is not defined.
5350 * \throw If \a this->getMeshDimension() < 1.
5352 bool MEDCouplingUMesh::areOnlySimplexCells() const
5354 checkFullyDefined();
5355 int mdim=getMeshDimension();
5356 if(mdim<1 || mdim>3)
5357 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5358 int nbCells=getNumberOfCells();
5359 const int *conn=_nodal_connec->getConstPointer();
5360 const int *connI=_nodal_connec_index->getConstPointer();
5361 for(int i=0;i<nbCells;i++)
5363 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5371 * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5373 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5375 checkConnectivityFullyDefined();
5376 if(getMeshDimension()!=2)
5377 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5378 int nbOfCells=getNumberOfCells();
5379 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5380 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5381 ret->alloc(nbOfCells+nbOfCutCells,1);
5382 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5383 int *retPt=ret->getPointer();
5384 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5385 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5386 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5387 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5388 int *pt=newConn->getPointer();
5389 int *ptI=newConnI->getPointer();
5391 const int *oldc=_nodal_connec->getConstPointer();
5392 const int *ci=_nodal_connec_index->getConstPointer();
5393 for(int i=0;i<nbOfCells;i++,ci++)
5395 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5397 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5398 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5399 pt=std::copy(tmp,tmp+8,pt);
5408 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5409 ptI[1]=ptI[0]+ci[1]-ci[0];
5414 _nodal_connec->decrRef();
5415 _nodal_connec=newConn.retn();
5416 _nodal_connec_index->decrRef();
5417 _nodal_connec_index=newConnI.retn();
5424 * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5426 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5428 checkConnectivityFullyDefined();
5429 if(getMeshDimension()!=2)
5430 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5431 int nbOfCells=getNumberOfCells();
5432 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5433 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5434 ret->alloc(nbOfCells+nbOfCutCells,1);
5435 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5436 int *retPt=ret->getPointer();
5437 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5438 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5439 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5440 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5441 int *pt=newConn->getPointer();
5442 int *ptI=newConnI->getPointer();
5444 const int *oldc=_nodal_connec->getConstPointer();
5445 const int *ci=_nodal_connec_index->getConstPointer();
5446 for(int i=0;i<nbOfCells;i++,ci++)
5448 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5450 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5451 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5452 pt=std::copy(tmp,tmp+8,pt);
5461 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5462 ptI[1]=ptI[0]+ci[1]-ci[0];
5467 _nodal_connec->decrRef();
5468 _nodal_connec=newConn.retn();
5469 _nodal_connec_index->decrRef();
5470 _nodal_connec_index=newConnI.retn();
5477 * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5479 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5481 checkConnectivityFullyDefined();
5482 if(getMeshDimension()!=3)
5483 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5484 int nbOfCells=getNumberOfCells();
5485 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5486 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5487 ret->alloc(nbOfCells+4*nbOfCutCells,1);
5488 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5489 int *retPt=ret->getPointer();
5490 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5491 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5492 newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5493 newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5494 int *pt=newConn->getPointer();
5495 int *ptI=newConnI->getPointer();
5497 const int *oldc=_nodal_connec->getConstPointer();
5498 const int *ci=_nodal_connec_index->getConstPointer();
5499 for(int i=0;i<nbOfCells;i++,ci++)
5501 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5503 for(int j=0;j<5;j++,pt+=5,ptI++)
5505 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5506 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];
5513 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5514 ptI[1]=ptI[0]+ci[1]-ci[0];
5519 _nodal_connec->decrRef();
5520 _nodal_connec=newConn.retn();
5521 _nodal_connec_index->decrRef();
5522 _nodal_connec_index=newConnI.retn();
5529 * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5531 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5533 checkConnectivityFullyDefined();
5534 if(getMeshDimension()!=3)
5535 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5536 int nbOfCells=getNumberOfCells();
5537 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5538 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5539 ret->alloc(nbOfCells+5*nbOfCutCells,1);
5540 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5541 int *retPt=ret->getPointer();
5542 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5543 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5544 newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5545 newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5546 int *pt=newConn->getPointer();
5547 int *ptI=newConnI->getPointer();
5549 const int *oldc=_nodal_connec->getConstPointer();
5550 const int *ci=_nodal_connec_index->getConstPointer();
5551 for(int i=0;i<nbOfCells;i++,ci++)
5553 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5555 for(int j=0;j<6;j++,pt+=5,ptI++)
5557 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5558 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];
5565 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5566 ptI[1]=ptI[0]+ci[1]-ci[0];
5571 _nodal_connec->decrRef();
5572 _nodal_connec=newConn.retn();
5573 _nodal_connec_index->decrRef();
5574 _nodal_connec_index=newConnI.retn();
5581 * 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.
5582 * This method completly ignore coordinates.
5583 * \param nodeSubdived is the nodal connectivity of subdivision of edges
5584 * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5585 * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5586 * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5588 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5590 checkFullyDefined();
5591 if(getMeshDimension()!=2)
5592 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5593 int nbOfCells=getNumberOfCells();
5594 int *connI=_nodal_connec_index->getPointer();
5596 for(int i=0;i<nbOfCells;i++,connI++)
5598 int offset=descIndex[i];
5599 int nbOfEdges=descIndex[i+1]-offset;
5601 bool ddirect=desc[offset+nbOfEdges-1]>0;
5602 int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5603 int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5604 for(int j=0;j<nbOfEdges;j++)
5606 bool direct=desc[offset+j]>0;
5607 int edgeId=std::abs(desc[offset+j])-1;
5608 if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5610 int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5611 int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5612 int ref2=direct?id1:id2;
5615 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5616 newConnLgth+=nbOfSubNodes-1;
5621 std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5622 throw INTERP_KERNEL::Exception(oss.str().c_str());
5627 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5630 newConnLgth++;//+1 is for cell type
5631 connI[1]=newConnLgth;
5634 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5635 newConn->alloc(newConnLgth,1);
5636 int *work=newConn->getPointer();
5637 for(int i=0;i<nbOfCells;i++)
5639 *work++=INTERP_KERNEL::NORM_POLYGON;
5640 int offset=descIndex[i];
5641 int nbOfEdges=descIndex[i+1]-offset;
5642 for(int j=0;j<nbOfEdges;j++)
5644 bool direct=desc[offset+j]>0;
5645 int edgeId=std::abs(desc[offset+j])-1;
5647 work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5650 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5651 std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5652 work=std::copy(it,it+nbOfSubNodes-1,work);
5656 DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5659 _types.insert(INTERP_KERNEL::NORM_POLYGON);
5663 * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5664 * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5665 * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5666 * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5667 * so it can be useful to call mergeNodes() before calling this method.
5668 * \throw If \a this->getMeshDimension() <= 1.
5669 * \throw If the coordinates array is not set.
5670 * \throw If the nodal connectivity of cells is not defined.
5672 void MEDCouplingUMesh::convertDegeneratedCells()
5674 checkFullyDefined();
5675 if(getMeshDimension()<=1)
5676 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5677 int nbOfCells=getNumberOfCells();
5680 int initMeshLgth=getMeshLength();
5681 int *conn=_nodal_connec->getPointer();
5682 int *index=_nodal_connec_index->getPointer();
5686 for(int i=0;i<nbOfCells;i++)
5688 lgthOfCurCell=index[i+1]-posOfCurCell;
5689 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5691 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5692 conn+newPos+1,newLgth);
5693 conn[newPos]=newType;
5695 posOfCurCell=index[i+1];
5698 if(newPos!=initMeshLgth)
5699 _nodal_connec->reAlloc(newPos);
5704 * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5705 * A cell is considered to be oriented correctly if an angle between its
5706 * normal vector and a given vector is less than \c PI / \c 2.
5707 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5709 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5711 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5712 * is not cleared before filling in.
5713 * \throw If \a this->getMeshDimension() != 2.
5714 * \throw If \a this->getSpaceDimension() != 3.
5716 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5717 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5719 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
5721 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5722 throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5723 int nbOfCells=getNumberOfCells();
5724 const int *conn=_nodal_connec->getConstPointer();
5725 const int *connI=_nodal_connec_index->getConstPointer();
5726 const double *coordsPtr=_coords->getConstPointer();
5727 for(int i=0;i<nbOfCells;i++)
5729 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5730 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5732 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5733 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5740 * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5741 * considered to be oriented correctly if an angle between its normal vector and a
5742 * given vector is less than \c PI / \c 2.
5743 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5745 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5747 * \throw If \a this->getMeshDimension() != 2.
5748 * \throw If \a this->getSpaceDimension() != 3.
5750 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5751 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5753 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
5755 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5756 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5757 int nbOfCells=getNumberOfCells();
5758 int *conn=_nodal_connec->getPointer();
5759 const int *connI=_nodal_connec_index->getConstPointer();
5760 const double *coordsPtr=_coords->getConstPointer();
5761 bool isModified=false;
5762 for(int i=0;i<nbOfCells;i++)
5764 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5765 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5767 bool isQuadratic(INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic());
5768 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5773 std::vector<int> tmp(connI[i+1]-connI[i]-2);
5774 std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5775 std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5779 int sz(((int)(connI[i+1]-connI[i]-1))/2);
5780 std::vector<int> tmp0(sz-1),tmp1(sz);
5781 std::copy(conn+connI[i]+2,conn+connI[i]+1+sz,tmp0.rbegin());
5782 std::copy(conn+connI[i]+1+sz,conn+connI[i+1],tmp1.rbegin());
5783 std::copy(tmp0.begin(),tmp0.end(),conn+connI[i]+2);
5784 std::copy(tmp1.begin(),tmp1.end(),conn+connI[i]+1+sz);
5790 _nodal_connec->declareAsNew();
5795 * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5796 * oriented facets. The normal vector of the facet should point out of the cell.
5797 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5798 * is not cleared before filling in.
5799 * \throw If \a this->getMeshDimension() != 3.
5800 * \throw If \a this->getSpaceDimension() != 3.
5801 * \throw If the coordinates array is not set.
5802 * \throw If the nodal connectivity of cells is not defined.
5804 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5805 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5807 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
5809 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5810 throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5811 int nbOfCells=getNumberOfCells();
5812 const int *conn=_nodal_connec->getConstPointer();
5813 const int *connI=_nodal_connec_index->getConstPointer();
5814 const double *coordsPtr=_coords->getConstPointer();
5815 for(int i=0;i<nbOfCells;i++)
5817 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5818 if(type==INTERP_KERNEL::NORM_POLYHED)
5820 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5827 * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
5829 * \throw If \a this->getMeshDimension() != 3.
5830 * \throw If \a this->getSpaceDimension() != 3.
5831 * \throw If the coordinates array is not set.
5832 * \throw If the nodal connectivity of cells is not defined.
5833 * \throw If the reparation fails.
5835 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5836 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5837 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5839 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
5841 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5842 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
5843 int nbOfCells=getNumberOfCells();
5844 int *conn=_nodal_connec->getPointer();
5845 const int *connI=_nodal_connec_index->getConstPointer();
5846 const double *coordsPtr=_coords->getConstPointer();
5847 for(int i=0;i<nbOfCells;i++)
5849 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5850 if(type==INTERP_KERNEL::NORM_POLYHED)
5854 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5855 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5857 catch(INTERP_KERNEL::Exception& e)
5859 std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
5860 throw INTERP_KERNEL::Exception(oss.str().c_str());
5868 * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
5869 * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
5870 * according to which the first facet of the cell should be oriented to have the normal vector
5871 * pointing out of cell.
5872 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
5873 * cells. The caller is to delete this array using decrRef() as it is no more
5875 * \throw If \a this->getMeshDimension() != 3.
5876 * \throw If \a this->getSpaceDimension() != 3.
5877 * \throw If the coordinates array is not set.
5878 * \throw If the nodal connectivity of cells is not defined.
5880 * \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
5881 * \ref py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
5882 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5884 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
5886 const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
5887 if(getMeshDimension()!=3)
5888 throw INTERP_KERNEL::Exception(msg);
5889 int spaceDim=getSpaceDimension();
5891 throw INTERP_KERNEL::Exception(msg);
5893 int nbOfCells=getNumberOfCells();
5894 int *conn=_nodal_connec->getPointer();
5895 const int *connI=_nodal_connec_index->getConstPointer();
5896 const double *coo=getCoords()->getConstPointer();
5897 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
5898 for(int i=0;i<nbOfCells;i++)
5900 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5901 if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
5903 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
5905 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5906 cells->pushBackSilent(i);
5910 return cells.retn();
5914 * This method is a faster method to correct orientation of all 3D cells in \a this.
5915 * 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.
5916 * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
5918 * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
5919 * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons,
5921 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
5923 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5924 throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
5925 int nbOfCells=getNumberOfCells();
5926 int *conn=_nodal_connec->getPointer();
5927 const int *connI=_nodal_connec_index->getConstPointer();
5928 const double *coordsPtr=_coords->getConstPointer();
5929 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5930 for(int i=0;i<nbOfCells;i++)
5932 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5935 case INTERP_KERNEL::NORM_TETRA4:
5937 if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5939 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
5940 ret->pushBackSilent(i);
5944 case INTERP_KERNEL::NORM_PYRA5:
5946 if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5948 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
5949 ret->pushBackSilent(i);
5953 case INTERP_KERNEL::NORM_PENTA6:
5954 case INTERP_KERNEL::NORM_HEXA8:
5955 case INTERP_KERNEL::NORM_HEXGP12:
5957 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5959 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5960 ret->pushBackSilent(i);
5964 case INTERP_KERNEL::NORM_POLYHED:
5966 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5968 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5969 ret->pushBackSilent(i);
5974 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 !");
5982 * This method has a sense for meshes with spaceDim==3 and meshDim==2.
5983 * If it is not the case an exception will be thrown.
5984 * This method is fast because the first cell of \a this is used to compute the plane.
5985 * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
5986 * \param pos output of size at least 3 used to store a point owned of searched plane.
5988 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
5990 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5991 throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
5992 const int *conn=_nodal_connec->getConstPointer();
5993 const int *connI=_nodal_connec_index->getConstPointer();
5994 const double *coordsPtr=_coords->getConstPointer();
5995 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
5996 std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6000 * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6001 * cells. Currently cells of the following types are treated:
6002 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6003 * For a cell of other type an exception is thrown.
6004 * Space dimension of a 2D mesh can be either 2 or 3.
6005 * The Edge Ratio of a cell \f$t\f$ is:
6006 * \f$\frac{|t|_\infty}{|t|_0}\f$,
6007 * where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6008 * the smallest edge lengths of \f$t\f$.
6009 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6010 * cells and one time, lying on \a this mesh. The caller is to delete this
6011 * field using decrRef() as it is no more needed.
6012 * \throw If the coordinates array is not set.
6013 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6014 * \throw If the connectivity data array has more than one component.
6015 * \throw If the connectivity data array has a named component.
6016 * \throw If the connectivity index data array has more than one component.
6017 * \throw If the connectivity index data array has a named component.
6018 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6019 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6020 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6022 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6025 int spaceDim=getSpaceDimension();
6026 int meshDim=getMeshDimension();
6027 if(spaceDim!=2 && spaceDim!=3)
6028 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6029 if(meshDim!=2 && meshDim!=3)
6030 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6031 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6033 int nbOfCells=getNumberOfCells();
6034 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6035 arr->alloc(nbOfCells,1);
6036 double *pt=arr->getPointer();
6037 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6038 const int *conn=_nodal_connec->getConstPointer();
6039 const int *connI=_nodal_connec_index->getConstPointer();
6040 const double *coo=_coords->getConstPointer();
6042 for(int i=0;i<nbOfCells;i++,pt++)
6044 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6047 case INTERP_KERNEL::NORM_TRI3:
6049 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6050 *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6053 case INTERP_KERNEL::NORM_QUAD4:
6055 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6056 *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6059 case INTERP_KERNEL::NORM_TETRA4:
6061 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6062 *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6066 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6068 conn+=connI[i+1]-connI[i];
6070 ret->setName("EdgeRatio");
6071 ret->synchronizeTimeWithSupport();
6076 * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6077 * cells. Currently cells of the following types are treated:
6078 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6079 * For a cell of other type an exception is thrown.
6080 * Space dimension of a 2D mesh can be either 2 or 3.
6081 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6082 * cells and one time, lying on \a this mesh. The caller is to delete this
6083 * field using decrRef() as it is no more needed.
6084 * \throw If the coordinates array is not set.
6085 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6086 * \throw If the connectivity data array has more than one component.
6087 * \throw If the connectivity data array has a named component.
6088 * \throw If the connectivity index data array has more than one component.
6089 * \throw If the connectivity index data array has a named component.
6090 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6091 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6092 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6094 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6097 int spaceDim=getSpaceDimension();
6098 int meshDim=getMeshDimension();
6099 if(spaceDim!=2 && spaceDim!=3)
6100 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6101 if(meshDim!=2 && meshDim!=3)
6102 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6103 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6105 int nbOfCells=getNumberOfCells();
6106 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6107 arr->alloc(nbOfCells,1);
6108 double *pt=arr->getPointer();
6109 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6110 const int *conn=_nodal_connec->getConstPointer();
6111 const int *connI=_nodal_connec_index->getConstPointer();
6112 const double *coo=_coords->getConstPointer();
6114 for(int i=0;i<nbOfCells;i++,pt++)
6116 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6119 case INTERP_KERNEL::NORM_TRI3:
6121 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6122 *pt=INTERP_KERNEL::triAspectRatio(tmp);
6125 case INTERP_KERNEL::NORM_QUAD4:
6127 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6128 *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6131 case INTERP_KERNEL::NORM_TETRA4:
6133 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6134 *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6138 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6140 conn+=connI[i+1]-connI[i];
6142 ret->setName("AspectRatio");
6143 ret->synchronizeTimeWithSupport();
6148 * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6149 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6150 * treated: INTERP_KERNEL::NORM_QUAD4.
6151 * For a cell of other type an exception is thrown.
6152 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6153 * cells and one time, lying on \a this mesh. The caller is to delete this
6154 * field using decrRef() as it is no more needed.
6155 * \throw If the coordinates array is not set.
6156 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6157 * \throw If the connectivity data array has more than one component.
6158 * \throw If the connectivity data array has a named component.
6159 * \throw If the connectivity index data array has more than one component.
6160 * \throw If the connectivity index data array has a named component.
6161 * \throw If \a this->getMeshDimension() != 2.
6162 * \throw If \a this->getSpaceDimension() != 3.
6163 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6165 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6168 int spaceDim=getSpaceDimension();
6169 int meshDim=getMeshDimension();
6171 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6173 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6174 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6176 int nbOfCells=getNumberOfCells();
6177 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6178 arr->alloc(nbOfCells,1);
6179 double *pt=arr->getPointer();
6180 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6181 const int *conn=_nodal_connec->getConstPointer();
6182 const int *connI=_nodal_connec_index->getConstPointer();
6183 const double *coo=_coords->getConstPointer();
6185 for(int i=0;i<nbOfCells;i++,pt++)
6187 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6190 case INTERP_KERNEL::NORM_QUAD4:
6192 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6193 *pt=INTERP_KERNEL::quadWarp(tmp);
6197 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6199 conn+=connI[i+1]-connI[i];
6201 ret->setName("Warp");
6202 ret->synchronizeTimeWithSupport();
6208 * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6209 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6210 * treated: INTERP_KERNEL::NORM_QUAD4.
6211 * For a cell of other type an exception is thrown.
6212 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6213 * cells and one time, lying on \a this mesh. The caller is to delete this
6214 * field using decrRef() as it is no more needed.
6215 * \throw If the coordinates array is not set.
6216 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6217 * \throw If the connectivity data array has more than one component.
6218 * \throw If the connectivity data array has a named component.
6219 * \throw If the connectivity index data array has more than one component.
6220 * \throw If the connectivity index data array has a named component.
6221 * \throw If \a this->getMeshDimension() != 2.
6222 * \throw If \a this->getSpaceDimension() != 3.
6223 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6225 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6228 int spaceDim=getSpaceDimension();
6229 int meshDim=getMeshDimension();
6231 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6233 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6234 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6236 int nbOfCells=getNumberOfCells();
6237 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6238 arr->alloc(nbOfCells,1);
6239 double *pt=arr->getPointer();
6240 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6241 const int *conn=_nodal_connec->getConstPointer();
6242 const int *connI=_nodal_connec_index->getConstPointer();
6243 const double *coo=_coords->getConstPointer();
6245 for(int i=0;i<nbOfCells;i++,pt++)
6247 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6250 case INTERP_KERNEL::NORM_QUAD4:
6252 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6253 *pt=INTERP_KERNEL::quadSkew(tmp);
6257 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6259 conn+=connI[i+1]-connI[i];
6261 ret->setName("Skew");
6262 ret->synchronizeTimeWithSupport();
6267 * This method aggregate the bbox of each cell and put it into bbox parameter.
6269 * \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)
6270 * For all other cases this input parameter is ignored.
6271 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6273 * \throw If \a this is not fully set (coordinates and connectivity).
6274 * \throw If a cell in \a this has no valid nodeId.
6275 * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6277 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6279 int mDim(getMeshDimension()),sDim(getSpaceDimension());
6280 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.
6281 return getBoundingBoxForBBTreeFast();
6282 if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6284 bool presenceOfQuadratic(false);
6285 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6287 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6288 if(cm.isQuadratic())
6289 presenceOfQuadratic=true;
6291 if(!presenceOfQuadratic)
6292 return getBoundingBoxForBBTreeFast();
6293 if(mDim==2 && sDim==2)
6294 return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6296 return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6298 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) !");
6302 * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6303 * So meshes having quadratic cells the computed bounding boxes can be invalid !
6305 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6307 * \throw If \a this is not fully set (coordinates and connectivity).
6308 * \throw If a cell in \a this has no valid nodeId.
6310 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6312 checkFullyDefined();
6313 int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6314 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6315 double *bbox(ret->getPointer());
6316 for(int i=0;i<nbOfCells*spaceDim;i++)
6318 bbox[2*i]=std::numeric_limits<double>::max();
6319 bbox[2*i+1]=-std::numeric_limits<double>::max();
6321 const double *coordsPtr(_coords->getConstPointer());
6322 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6323 for(int i=0;i<nbOfCells;i++)
6325 int offset=connI[i]+1;
6326 int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6327 for(int j=0;j<nbOfNodesForCell;j++)
6329 int nodeId=conn[offset+j];
6330 if(nodeId>=0 && nodeId<nbOfNodes)
6332 for(int k=0;k<spaceDim;k++)
6334 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6335 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6342 std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6343 throw INTERP_KERNEL::Exception(oss.str().c_str());
6350 * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6351 * useful for 2D meshes having quadratic cells
6352 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6353 * the two extremities of the arc of circle).
6355 * \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)
6356 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6357 * \throw If \a this is not fully defined.
6358 * \throw If \a this is not a mesh with meshDimension equal to 2.
6359 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6360 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6362 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6364 checkFullyDefined();
6365 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6366 if(spaceDim!=2 || spaceDim!=2)
6367 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!");
6368 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6369 double *bbox(ret->getPointer());
6370 const double *coords(_coords->getConstPointer());
6371 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6372 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6374 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6375 int sz(connI[1]-connI[0]-1);
6376 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6377 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6378 INTERP_KERNEL::QuadraticPolygon *pol(0);
6379 for(int j=0;j<sz;j++)
6381 int nodeId(conn[*connI+1+j]);
6382 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6384 if(!cm.isQuadratic())
6385 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6387 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6388 INTERP_KERNEL::Bounds b; pol->fillBounds(b); delete pol;
6389 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax();
6395 * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6396 * useful for 2D meshes having quadratic cells
6397 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6398 * the two extremities of the arc of circle).
6400 * \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)
6401 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6402 * \throw If \a this is not fully defined.
6403 * \throw If \a this is not a mesh with meshDimension equal to 1.
6404 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6405 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6407 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6409 checkFullyDefined();
6410 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6411 if(spaceDim!=2 || spaceDim!=2)
6412 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!");
6413 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6414 double *bbox(ret->getPointer());
6415 const double *coords(_coords->getConstPointer());
6416 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6417 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6419 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6420 int sz(connI[1]-connI[0]-1);
6421 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6422 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6423 INTERP_KERNEL::Edge *edge(0);
6424 for(int j=0;j<sz;j++)
6426 int nodeId(conn[*connI+1+j]);
6427 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6429 if(!cm.isQuadratic())
6430 edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6432 edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6433 const INTERP_KERNEL::Bounds& b(edge->getBounds());
6434 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6441 namespace ParaMEDMEMImpl
6446 ConnReader(const int *c, int val):_conn(c),_val(val) { }
6447 bool operator() (const int& pos) { return _conn[pos]!=_val; }
6456 ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6457 bool operator() (const int& pos) { return _conn[pos]==_val; }
6467 * This method expects that \a this is sorted by types. If not an exception will be thrown.
6468 * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6469 * \a this is composed in cell types.
6470 * The returned array is of size 3*n where n is the number of different types present in \a this.
6471 * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here.
6472 * This parameter is kept only for compatibility with other methode listed above.
6474 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6476 checkConnectivityFullyDefined();
6477 const int *conn=_nodal_connec->getConstPointer();
6478 const int *connI=_nodal_connec_index->getConstPointer();
6479 const int *work=connI;
6480 int nbOfCells=getNumberOfCells();
6481 std::size_t n=getAllGeoTypes().size();
6482 std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6483 std::set<INTERP_KERNEL::NormalizedCellType> types;
6484 for(std::size_t i=0;work!=connI+nbOfCells;i++)
6486 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6487 if(types.find(typ)!=types.end())
6489 std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6490 oss << " is not contiguous !";
6491 throw INTERP_KERNEL::Exception(oss.str().c_str());
6495 const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6496 ret[3*i+1]=(int)std::distance(work,work2);
6503 * This method is used to check that this has contiguous cell type in same order than described in \a code.
6504 * only for types cell, type node is not managed.
6505 * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6506 * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6507 * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6508 * If 2 or more same geometric type is in \a code and exception is thrown too.
6510 * This method firstly checks
6511 * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6512 * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6513 * an exception is thrown too.
6515 * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6516 * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown
6517 * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6519 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6522 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6523 std::size_t sz=code.size();
6526 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6527 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6529 bool isNoPflUsed=true;
6530 for(std::size_t i=0;i<n;i++)
6531 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6533 types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6535 if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6536 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6537 isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6540 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6543 if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6544 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6545 if(types.size()==_types.size())
6548 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6550 int *retPtr=ret->getPointer();
6551 const int *connI=_nodal_connec_index->getConstPointer();
6552 const int *conn=_nodal_connec->getConstPointer();
6553 int nbOfCells=getNumberOfCells();
6556 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6558 i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6559 int offset=(int)std::distance(connI,i);
6560 const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6561 int nbOfCellsOfCurType=(int)std::distance(i,j);
6562 if(code[3*kk+2]==-1)
6563 for(int k=0;k<nbOfCellsOfCurType;k++)
6567 int idInIdsPerType=code[3*kk+2];
6568 if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6570 const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6573 zePfl->checkAllocated();
6574 if(zePfl->getNumberOfComponents()==1)
6576 for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6578 if(*k>=0 && *k<nbOfCellsOfCurType)
6579 *retPtr=(*k)+offset;
6582 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6583 oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6584 throw INTERP_KERNEL::Exception(oss.str().c_str());
6589 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6592 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6596 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6597 oss << " should be in [0," << idsPerType.size() << ") !";
6598 throw INTERP_KERNEL::Exception(oss.str().c_str());
6607 * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6608 * 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.
6609 * 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.
6610 * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6612 * \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.
6613 * \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,
6614 * \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6615 * \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.
6616 * This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6617 * \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
6619 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6622 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6623 if(profile->getNumberOfComponents()!=1)
6624 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6625 checkConnectivityFullyDefined();
6626 const int *conn=_nodal_connec->getConstPointer();
6627 const int *connI=_nodal_connec_index->getConstPointer();
6628 int nbOfCells=getNumberOfCells();
6629 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6630 std::vector<int> typeRangeVals(1);
6631 for(const int *i=connI;i!=connI+nbOfCells;)
6633 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6634 if(std::find(types.begin(),types.end(),curType)!=types.end())
6636 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6638 types.push_back(curType);
6639 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6640 typeRangeVals.push_back((int)std::distance(connI,i));
6643 DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6644 profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6645 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6646 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6647 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6649 int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6650 code.resize(3*nbOfCastsFinal);
6651 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6652 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6653 for(int i=0;i<nbOfCastsFinal;i++)
6655 int castId=castsPresent->getIJ(i,0);
6656 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6657 idsInPflPerType2.push_back(tmp3);
6658 code[3*i]=(int)types[castId];
6659 code[3*i+1]=tmp3->getNumberOfTuples();
6660 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6661 if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6663 tmp4->copyStringInfoFrom(*profile);
6664 idsPerType2.push_back(tmp4);
6665 code[3*i+2]=(int)idsPerType2.size()-1;
6672 std::size_t sz2=idsInPflPerType2.size();
6673 idsInPflPerType.resize(sz2);
6674 for(std::size_t i=0;i<sz2;i++)
6676 DataArrayInt *locDa=idsInPflPerType2[i];
6678 idsInPflPerType[i]=locDa;
6680 std::size_t sz=idsPerType2.size();
6681 idsPerType.resize(sz);
6682 for(std::size_t i=0;i<sz;i++)
6684 DataArrayInt *locDa=idsPerType2[i];
6686 idsPerType[i]=locDa;
6691 * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6692 * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6693 * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6694 * 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.
6696 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
6698 checkFullyDefined();
6699 nM1LevMesh->checkFullyDefined();
6700 if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6701 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6702 if(_coords!=nM1LevMesh->getCoords())
6703 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6704 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6705 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6706 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6707 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6708 desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6709 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6710 tmp->setConnectivity(tmp0,tmp1);
6711 tmp->renumberCells(ret0->getConstPointer(),false);
6712 revDesc=tmp->getNodalConnectivity();
6713 revDescIndx=tmp->getNodalConnectivityIndex();
6714 DataArrayInt *ret=0;
6715 if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6718 ret->getMaxValue(tmp2);
6720 std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6721 throw INTERP_KERNEL::Exception(oss.str().c_str());
6726 revDescIndx->incrRef();
6729 meshnM1Old2New=ret0;
6734 * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6735 * necessary for writing the mesh to MED file. Additionally returns a permutation array
6736 * in "Old to New" mode.
6737 * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6738 * this array using decrRef() as it is no more needed.
6739 * \throw If the nodal connectivity of cells is not defined.
6741 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
6743 checkConnectivityFullyDefined();
6744 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6745 renumberCells(ret->getConstPointer(),false);
6750 * This methods checks that cells are sorted by their types.
6751 * This method makes asumption (no check) that connectivity is correctly set before calling.
6753 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6755 checkFullyDefined();
6756 const int *conn=_nodal_connec->getConstPointer();
6757 const int *connI=_nodal_connec_index->getConstPointer();
6758 int nbOfCells=getNumberOfCells();
6759 std::set<INTERP_KERNEL::NormalizedCellType> types;
6760 for(const int *i=connI;i!=connI+nbOfCells;)
6762 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6763 if(types.find(curType)!=types.end())
6765 types.insert(curType);
6766 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6772 * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6773 * The geometric type order is specified by MED file.
6775 * \sa MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6777 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
6779 return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6783 * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6784 * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
6785 * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6786 * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6788 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6790 checkFullyDefined();
6791 const int *conn=_nodal_connec->getConstPointer();
6792 const int *connI=_nodal_connec_index->getConstPointer();
6793 int nbOfCells=getNumberOfCells();
6797 std::set<INTERP_KERNEL::NormalizedCellType> sg;
6798 for(const int *i=connI;i!=connI+nbOfCells;)
6800 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6801 const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6802 if(isTypeExists!=orderEnd)
6804 int pos=(int)std::distance(orderBg,isTypeExists);
6808 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6812 if(sg.find(curType)==sg.end())
6814 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6825 * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6826 * 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
6827 * 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'.
6829 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
6831 checkConnectivityFullyDefined();
6832 int nbOfCells=getNumberOfCells();
6833 const int *conn=_nodal_connec->getConstPointer();
6834 const int *connI=_nodal_connec_index->getConstPointer();
6835 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6836 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6837 tmpa->alloc(nbOfCells,1);
6838 tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6839 tmpb->fillWithZero();
6840 int *tmp=tmpa->getPointer();
6841 int *tmp2=tmpb->getPointer();
6842 for(const int *i=connI;i!=connI+nbOfCells;i++)
6844 const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6847 int pos=(int)std::distance(orderBg,where);
6849 tmp[std::distance(connI,i)]=pos;
6853 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6854 std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6855 oss << " has a type " << cm.getRepr() << " not in input array of type !";
6856 throw INTERP_KERNEL::Exception(oss.str().c_str());
6859 nbPerType=tmpb.retn();
6864 * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
6866 * \return a new object containing the old to new correspondance.
6868 * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6870 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
6872 return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6876 * 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.
6877 * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6878 * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6879 * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6881 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6883 DataArrayInt *nbPerType=0;
6884 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6885 nbPerType->decrRef();
6886 return tmpa->buildPermArrPerLevel();
6890 * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
6891 * The number of cells remains unchanged after the call of this method.
6892 * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6893 * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6895 * \return the array giving the correspondance old to new.
6897 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6899 checkFullyDefined();
6901 const int *conn=_nodal_connec->getConstPointer();
6902 const int *connI=_nodal_connec_index->getConstPointer();
6903 int nbOfCells=getNumberOfCells();
6904 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6905 for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6906 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6908 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6909 types.push_back(curType);
6910 for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6912 DataArrayInt *ret=DataArrayInt::New();
6913 ret->alloc(nbOfCells,1);
6914 int *retPtr=ret->getPointer();
6915 std::fill(retPtr,retPtr+nbOfCells,-1);
6917 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6919 for(const int *i=connI;i!=connI+nbOfCells;i++)
6920 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6921 retPtr[std::distance(connI,i)]=newCellId++;
6923 renumberCells(retPtr,false);
6928 * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
6929 * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
6930 * This method makes asumption that connectivity is correctly set before calling.
6932 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
6934 checkConnectivityFullyDefined();
6935 const int *conn=_nodal_connec->getConstPointer();
6936 const int *connI=_nodal_connec_index->getConstPointer();
6937 int nbOfCells=getNumberOfCells();
6938 std::vector<MEDCouplingUMesh *> ret;
6939 for(const int *i=connI;i!=connI+nbOfCells;)
6941 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6942 int beginCellId=(int)std::distance(connI,i);
6943 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6944 int endCellId=(int)std::distance(connI,i);
6945 int sz=endCellId-beginCellId;
6946 int *cells=new int[sz];
6947 for(int j=0;j<sz;j++)
6948 cells[j]=beginCellId+j;
6949 MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
6957 * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
6958 * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
6959 * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
6961 * \return a newly allocated instance, that the caller must manage.
6962 * \throw If \a this contains more than one geometric type.
6963 * \throw If the nodal connectivity of \a this is not fully defined.
6964 * \throw If the internal data is not coherent.
6966 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
6968 checkConnectivityFullyDefined();
6969 if(_types.size()!=1)
6970 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6971 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6972 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
6973 ret->setCoords(getCoords());
6974 MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6977 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
6978 retC->setNodalConnectivity(c);
6982 MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6984 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
6985 DataArrayInt *c=0,*ci=0;
6986 convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
6987 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
6988 retD->setNodalConnectivity(cs,cis);
6993 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
6995 checkConnectivityFullyDefined();
6996 if(_types.size()!=1)
6997 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6998 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6999 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7002 std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7003 oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7004 throw INTERP_KERNEL::Exception(oss.str().c_str());
7006 int nbCells=getNumberOfCells();
7008 int nbNodesPerCell=(int)cm.getNumberOfNodes();
7009 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7010 int *outPtr=connOut->getPointer();
7011 const int *conn=_nodal_connec->begin();
7012 const int *connI=_nodal_connec_index->begin();
7014 for(int i=0;i<nbCells;i++,connI++)
7016 if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7017 outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7020 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 << ") !";
7021 throw INTERP_KERNEL::Exception(oss.str().c_str());
7024 return connOut.retn();
7027 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7029 static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7030 checkConnectivityFullyDefined();
7031 if(_types.size()!=1)
7032 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7033 int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7035 throw INTERP_KERNEL::Exception(msg0);
7036 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7037 c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7038 int *cp(c->getPointer()),*cip(ci->getPointer());
7039 const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7041 for(int i=0;i<nbCells;i++,cip++,incip++)
7043 int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7044 int delta(stop-strt);
7047 if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7048 cp=std::copy(incp+strt,incp+stop,cp);
7050 throw INTERP_KERNEL::Exception(msg0);
7053 throw INTERP_KERNEL::Exception(msg0);
7054 cip[1]=cip[0]+delta;
7056 nodalConn=c.retn(); nodalConnIndex=ci.retn();
7060 * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7061 * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7062 * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7063 * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7064 * are not used here to avoid the build of big permutation array.
7066 * \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
7067 * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7068 * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7069 * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7070 * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7071 * output array gives for each chunck of same type the corresponding mesh id in \b ms.
7072 * \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
7073 * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7075 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7076 DataArrayInt *&szOfCellGrpOfSameType,
7077 DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
7079 std::vector<const MEDCouplingUMesh *> ms2;
7080 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7083 (*it)->checkConnectivityFullyDefined();
7087 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7088 const DataArrayDouble *refCoo=ms2[0]->getCoords();
7089 int meshDim=ms2[0]->getMeshDimension();
7090 std::vector<const MEDCouplingUMesh *> m1ssm;
7091 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7093 std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7094 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7096 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7097 ret1->alloc(0,1); ret2->alloc(0,1);
7098 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7100 if(meshDim!=(*it)->getMeshDimension())
7101 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7102 if(refCoo!=(*it)->getCoords())
7103 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7104 std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7105 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7106 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7107 for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7109 MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7110 m1ssmSingleAuto.push_back(singleCell);
7111 m1ssmSingle.push_back(singleCell);
7112 ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7115 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7116 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7117 std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7118 for(std::size_t i=0;i<m1ssm.size();i++)
7119 m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7120 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7121 szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7122 idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7127 * This method returns a newly created DataArrayInt instance.
7128 * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7130 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7132 checkFullyDefined();
7133 const int *conn=_nodal_connec->getConstPointer();
7134 const int *connIndex=_nodal_connec_index->getConstPointer();
7135 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7136 for(const int *w=begin;w!=end;w++)
7137 if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7138 ret->pushBackSilent(*w);
7143 * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7144 * are in [0:getNumberOfCells())
7146 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7148 checkFullyDefined();
7149 const int *conn=_nodal_connec->getConstPointer();
7150 const int *connI=_nodal_connec_index->getConstPointer();
7151 int nbOfCells=getNumberOfCells();
7152 std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7153 int *tmp=new int[nbOfCells];
7154 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7157 for(const int *i=connI;i!=connI+nbOfCells;i++)
7158 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7159 tmp[std::distance(connI,i)]=j++;
7161 DataArrayInt *ret=DataArrayInt::New();
7162 ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7163 ret->copyStringInfoFrom(*da);
7164 int *retPtr=ret->getPointer();
7165 const int *daPtr=da->getConstPointer();
7166 int nbOfElems=da->getNbOfElems();
7167 for(int k=0;k<nbOfElems;k++)
7168 retPtr[k]=tmp[daPtr[k]];
7174 * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7175 * This method \b works \b for mesh sorted by type.
7176 * cells whose ids is in 'idsPerGeoType' array.
7177 * This method conserves coords and name of mesh.
7179 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7181 std::vector<int> code=getDistributionOfTypes();
7182 std::size_t nOfTypesInThis=code.size()/3;
7183 int sz=0,szOfType=0;
7184 for(std::size_t i=0;i<nOfTypesInThis;i++)
7189 szOfType=code[3*i+1];
7191 for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7192 if(*work<0 || *work>=szOfType)
7194 std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7195 oss << ". It should be in [0," << szOfType << ") !";
7196 throw INTERP_KERNEL::Exception(oss.str().c_str());
7198 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7199 int *idsPtr=idsTokeep->getPointer();
7201 for(std::size_t i=0;i<nOfTypesInThis;i++)
7204 for(int j=0;j<code[3*i+1];j++)
7207 idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7208 offset+=code[3*i+1];
7210 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7211 ret->copyTinyInfoFrom(this);
7216 * This method returns a vector of size 'this->getNumberOfCells()'.
7217 * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7219 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7221 int ncell=getNumberOfCells();
7222 std::vector<bool> ret(ncell);
7223 const int *cI=getNodalConnectivityIndex()->getConstPointer();
7224 const int *c=getNodalConnectivity()->getConstPointer();
7225 for(int i=0;i<ncell;i++)
7227 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7228 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7229 ret[i]=cm.isQuadratic();
7235 * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7237 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7239 if(other->getType()!=UNSTRUCTURED)
7240 throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7241 const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7242 return MergeUMeshes(this,otherC);
7246 * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7247 * computed by averaging coordinates of cell nodes, so this method is not a right
7248 * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7249 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7250 * this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7251 * components. The caller is to delete this array using decrRef() as it is
7253 * \throw If the coordinates array is not set.
7254 * \throw If the nodal connectivity of cells is not defined.
7255 * \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7257 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7259 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7260 int spaceDim=getSpaceDimension();
7261 int nbOfCells=getNumberOfCells();
7262 ret->alloc(nbOfCells,spaceDim);
7263 ret->copyStringInfoFrom(*getCoords());
7264 double *ptToFill=ret->getPointer();
7265 const int *nodal=_nodal_connec->getConstPointer();
7266 const int *nodalI=_nodal_connec_index->getConstPointer();
7267 const double *coor=_coords->getConstPointer();
7268 for(int i=0;i<nbOfCells;i++)
7270 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7271 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7278 * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7279 * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the
7281 * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned
7282 * DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7284 * \sa MEDCouplingUMesh::getBarycenterAndOwner
7285 * \throw If \a this is not fully defined (coordinates and connectivity)
7286 * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7288 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7290 checkFullyDefined();
7291 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7292 int spaceDim=getSpaceDimension();
7293 int nbOfCells=getNumberOfCells();
7294 int nbOfNodes=getNumberOfNodes();
7295 ret->alloc(nbOfCells,spaceDim);
7296 double *ptToFill=ret->getPointer();
7297 const int *nodal=_nodal_connec->getConstPointer();
7298 const int *nodalI=_nodal_connec_index->getConstPointer();
7299 const double *coor=_coords->getConstPointer();
7300 for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7302 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7303 std::fill(ptToFill,ptToFill+spaceDim,0.);
7304 if(type!=INTERP_KERNEL::NORM_POLYHED)
7306 for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7308 if(*conn>=0 && *conn<nbOfNodes)
7309 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7312 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," << nbOfNodes << ") !";
7313 throw INTERP_KERNEL::Exception(oss.str().c_str());
7316 int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7317 if(nbOfNodesInCell>0)
7318 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7321 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7322 throw INTERP_KERNEL::Exception(oss.str().c_str());
7327 std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7329 for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7331 if(*it>=0 && *it<nbOfNodes)
7332 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7335 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," << nbOfNodes << ") !";
7336 throw INTERP_KERNEL::Exception(oss.str().c_str());
7340 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7343 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7344 throw INTERP_KERNEL::Exception(oss.str().c_str());
7352 * Returns a new DataArrayDouble holding barycenters of specified cells. The
7353 * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7354 * are specified via an array of cell ids.
7355 * \warning Validity of the specified cell ids is not checked!
7356 * Valid range is [ 0, \a this->getNumberOfCells() ).
7357 * \param [in] begin - an array of cell ids of interest.
7358 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7359 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7360 * end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7361 * caller is to delete this array using decrRef() as it is no more needed.
7362 * \throw If the coordinates array is not set.
7363 * \throw If the nodal connectivity of cells is not defined.
7365 * \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7366 * \ref py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7368 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7370 DataArrayDouble *ret=DataArrayDouble::New();
7371 int spaceDim=getSpaceDimension();
7372 int nbOfTuple=(int)std::distance(begin,end);
7373 ret->alloc(nbOfTuple,spaceDim);
7374 double *ptToFill=ret->getPointer();
7375 double *tmp=new double[spaceDim];
7376 const int *nodal=_nodal_connec->getConstPointer();
7377 const int *nodalI=_nodal_connec_index->getConstPointer();
7378 const double *coor=_coords->getConstPointer();
7379 for(const int *w=begin;w!=end;w++)
7381 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7382 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7390 * 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".
7391 * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7392 * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7393 * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7394 * This method is useful to detect 2D cells in 3D space that are not coplanar.
7396 * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7397 * \throw If spaceDim!=3 or meshDim!=2.
7398 * \throw If connectivity of \a this is invalid.
7399 * \throw If connectivity of a cell in \a this points to an invalid node.
7401 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7403 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7404 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7405 if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7406 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7407 ret->alloc(nbOfCells,4);
7408 double *retPtr(ret->getPointer());
7409 const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7410 const double *coor(_coords->begin());
7411 for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7413 double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7414 if(nodalI[1]-nodalI[0]>=3)
7416 for(int j=0;j<3;j++)
7418 int nodeId(nodal[nodalI[0]+1+j]);
7419 if(nodeId>=0 && nodeId<nbOfNodes)
7420 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7423 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7424 throw INTERP_KERNEL::Exception(oss.str().c_str());
7430 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7431 throw INTERP_KERNEL::Exception(oss.str().c_str());
7433 INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7434 retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7440 * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7443 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7446 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7447 da->checkAllocated();
7448 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7450 int nbOfTuples=da->getNumberOfTuples();
7451 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7452 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7453 c->alloc(2*nbOfTuples,1);
7454 cI->alloc(nbOfTuples+1,1);
7455 int *cp=c->getPointer();
7456 int *cip=cI->getPointer();
7458 for(int i=0;i<nbOfTuples;i++)
7460 *cp++=INTERP_KERNEL::NORM_POINT1;
7464 ret->setConnectivity(c,cI,true);
7468 * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7469 * Cells and nodes of
7470 * the first mesh precede cells and nodes of the second mesh within the result mesh.
7471 * \param [in] mesh1 - the first mesh.
7472 * \param [in] mesh2 - the second mesh.
7473 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7474 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7475 * is no more needed.
7476 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7477 * \throw If the coordinates array is not set in none of the meshes.
7478 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7479 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7481 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7483 std::vector<const MEDCouplingUMesh *> tmp(2);
7484 tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7485 return MergeUMeshes(tmp);
7489 * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7490 * Cells and nodes of
7491 * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7492 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7493 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7494 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7495 * is no more needed.
7496 * \throw If \a a.size() == 0.
7497 * \throw If \a a[ *i* ] == NULL.
7498 * \throw If the coordinates array is not set in none of the meshes.
7499 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7500 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7502 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7504 std::size_t sz=a.size();
7506 return MergeUMeshesLL(a);
7507 for(std::size_t ii=0;ii<sz;ii++)
7510 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7511 throw INTERP_KERNEL::Exception(oss.str().c_str());
7513 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7514 std::vector< const MEDCouplingUMesh * > aa(sz);
7516 for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7518 const MEDCouplingUMesh *cur=a[i];
7519 const DataArrayDouble *coo=cur->getCoords();
7521 spaceDim=coo->getNumberOfComponents();
7524 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7525 for(std::size_t i=0;i<sz;i++)
7527 bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7530 return MergeUMeshesLL(aa);
7535 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7538 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7539 std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7540 int meshDim=(*it)->getMeshDimension();
7541 int nbOfCells=(*it)->getNumberOfCells();
7542 int meshLgth=(*it++)->getMeshLength();
7543 for(;it!=a.end();it++)
7545 if(meshDim!=(*it)->getMeshDimension())
7546 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7547 nbOfCells+=(*it)->getNumberOfCells();
7548 meshLgth+=(*it)->getMeshLength();
7550 std::vector<const MEDCouplingPointSet *> aps(a.size());
7551 std::copy(a.begin(),a.end(),aps.begin());
7552 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7553 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7554 ret->setCoords(pts);
7555 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7556 c->alloc(meshLgth,1);
7557 int *cPtr=c->getPointer();
7558 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7559 cI->alloc(nbOfCells+1,1);
7560 int *cIPtr=cI->getPointer();
7564 for(it=a.begin();it!=a.end();it++)
7566 int curNbOfCell=(*it)->getNumberOfCells();
7567 const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7568 const int *curC=(*it)->_nodal_connec->getConstPointer();
7569 cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7570 for(int j=0;j<curNbOfCell;j++)
7572 const int *src=curC+curCI[j];
7574 for(;src!=curC+curCI[j+1];src++,cPtr++)
7582 offset+=curCI[curNbOfCell];
7583 offset2+=(*it)->getNumberOfNodes();
7586 ret->setConnectivity(c,cI,true);
7593 * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7594 * dimension and sharing the node coordinates array.
7595 * All cells of the first mesh precede all cells of the second mesh
7596 * within the result mesh.
7597 * \param [in] mesh1 - the first mesh.
7598 * \param [in] mesh2 - the second mesh.
7599 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7600 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7601 * is no more needed.
7602 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7603 * \throw If the meshes do not share the node coordinates array.
7604 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7605 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7607 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7609 std::vector<const MEDCouplingUMesh *> tmp(2);
7610 tmp[0]=mesh1; tmp[1]=mesh2;
7611 return MergeUMeshesOnSameCoords(tmp);
7615 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7616 * dimension and sharing the node coordinates array.
7617 * All cells of the *i*-th mesh precede all cells of the
7618 * (*i*+1)-th mesh within the result mesh.
7619 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7620 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7621 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7622 * is no more needed.
7623 * \throw If \a a.size() == 0.
7624 * \throw If \a a[ *i* ] == NULL.
7625 * \throw If the meshes do not share the node coordinates array.
7626 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7627 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7629 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7632 throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7633 for(std::size_t ii=0;ii<meshes.size();ii++)
7636 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7637 throw INTERP_KERNEL::Exception(oss.str().c_str());
7639 const DataArrayDouble *coords=meshes.front()->getCoords();
7640 int meshDim=meshes.front()->getMeshDimension();
7641 std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7643 int meshIndexLgth=0;
7644 for(;iter!=meshes.end();iter++)
7646 if(coords!=(*iter)->getCoords())
7647 throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7648 if(meshDim!=(*iter)->getMeshDimension())
7649 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7650 meshLgth+=(*iter)->getMeshLength();
7651 meshIndexLgth+=(*iter)->getNumberOfCells();
7653 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7654 nodal->alloc(meshLgth,1);
7655 int *nodalPtr=nodal->getPointer();
7656 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7657 nodalIndex->alloc(meshIndexLgth+1,1);
7658 int *nodalIndexPtr=nodalIndex->getPointer();
7660 for(iter=meshes.begin();iter!=meshes.end();iter++)
7662 const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7663 const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7664 int nbOfCells=(*iter)->getNumberOfCells();
7665 int meshLgth2=(*iter)->getMeshLength();
7666 nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7667 if(iter!=meshes.begin())
7668 nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7670 nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7673 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7674 ret->setName("merge");
7675 ret->setMeshDimension(meshDim);
7676 ret->setConnectivity(nodal,nodalIndex,true);
7677 ret->setCoords(coords);
7682 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7683 * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7684 * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7685 * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7686 * New" mode are returned for each input mesh.
7687 * \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7688 * \param [in] compType - specifies a cell comparison technique. For meaning of its
7689 * valid values [0,1,2], see zipConnectivityTraducer().
7690 * \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7691 * meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7692 * mesh. The caller is to delete each of the arrays using decrRef() as it is
7694 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7695 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7696 * is no more needed.
7697 * \throw If \a meshes.size() == 0.
7698 * \throw If \a meshes[ *i* ] == NULL.
7699 * \throw If the meshes do not share the node coordinates array.
7700 * \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7701 * \throw If the \a meshes are of different dimension (getMeshDimension()).
7702 * \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7703 * \throw If the nodal connectivity any of \a meshes includes an invalid id.
7705 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7707 //All checks are delegated to MergeUMeshesOnSameCoords
7708 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7709 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7710 corr.resize(meshes.size());
7711 std::size_t nbOfMeshes=meshes.size();
7713 const int *o2nPtr=o2n->getConstPointer();
7714 for(std::size_t i=0;i<nbOfMeshes;i++)
7716 DataArrayInt *tmp=DataArrayInt::New();
7717 int curNbOfCells=meshes[i]->getNumberOfCells();
7718 tmp->alloc(curNbOfCells,1);
7719 std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7720 offset+=curNbOfCells;
7721 tmp->setName(meshes[i]->getName());
7728 * Makes all given meshes share the nodal connectivity array. The common connectivity
7729 * array is created by concatenating the connectivity arrays of all given meshes. All
7730 * the given meshes must be of the same space dimension but dimension of cells **can
7731 * differ**. This method is particulary useful in MEDLoader context to build a \ref
7732 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7733 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7734 * \param [in,out] meshes - a vector of meshes to update.
7735 * \throw If any of \a meshes is NULL.
7736 * \throw If the coordinates array is not set in any of \a meshes.
7737 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7738 * \throw If \a meshes are of different space dimension.
7740 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
7742 std::size_t sz=meshes.size();
7745 std::vector< const DataArrayDouble * > coords(meshes.size());
7746 std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7747 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7751 (*it)->checkConnectivityFullyDefined();
7752 const DataArrayDouble *coo=(*it)->getCoords();
7757 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7758 oss << " has no coordinate array defined !";
7759 throw INTERP_KERNEL::Exception(oss.str().c_str());
7764 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7765 oss << " is null !";
7766 throw INTERP_KERNEL::Exception(oss.str().c_str());
7769 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7770 std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7771 int offset=(*it)->getNumberOfNodes();
7772 (*it++)->setCoords(res);
7773 for(;it!=meshes.end();it++)
7775 int oldNumberOfNodes=(*it)->getNumberOfNodes();
7776 (*it)->setCoords(res);
7777 (*it)->shiftNodeNumbersInConn(offset);
7778 offset+=oldNumberOfNodes;
7783 * Merges nodes coincident with a given precision within all given meshes that share
7784 * the nodal connectivity array. The given meshes **can be of different** mesh
7785 * dimension. This method is particulary useful in MEDLoader context to build a \ref
7786 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7787 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7788 * \param [in,out] meshes - a vector of meshes to update.
7789 * \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7790 * \throw If any of \a meshes is NULL.
7791 * \throw If the \a meshes do not share the same node coordinates array.
7792 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7794 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
7798 std::set<const DataArrayDouble *> s;
7799 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7802 s.insert((*it)->getCoords());
7805 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 !";
7806 throw INTERP_KERNEL::Exception(oss.str().c_str());
7811 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 !";
7812 throw INTERP_KERNEL::Exception(oss.str().c_str());
7814 const DataArrayDouble *coo=*(s.begin());
7818 DataArrayInt *comm,*commI;
7819 coo->findCommonTuples(eps,-1,comm,commI);
7820 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7821 int oldNbOfNodes=coo->getNumberOfTuples();
7823 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7824 if(oldNbOfNodes==newNbOfNodes)
7826 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7827 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7829 (*it)->renumberNodesInConn(o2n->getConstPointer());
7830 (*it)->setCoords(newCoords);
7835 * 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.
7836 * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7837 * \param isQuad specifies the policy of connectivity.
7838 * @ret in/out parameter in which the result will be append
7840 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7842 INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7843 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7844 ret.push_back(cm.getExtrudedType());
7845 int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7848 case INTERP_KERNEL::NORM_POINT1:
7850 ret.push_back(connBg[1]);
7851 ret.push_back(connBg[1]+nbOfNodesPerLev);
7854 case INTERP_KERNEL::NORM_SEG2:
7856 int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7857 ret.insert(ret.end(),conn,conn+4);
7860 case INTERP_KERNEL::NORM_SEG3:
7862 int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
7863 ret.insert(ret.end(),conn,conn+8);
7866 case INTERP_KERNEL::NORM_QUAD4:
7868 int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
7869 ret.insert(ret.end(),conn,conn+8);
7872 case INTERP_KERNEL::NORM_TRI3:
7874 int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
7875 ret.insert(ret.end(),conn,conn+6);
7878 case INTERP_KERNEL::NORM_TRI6:
7880 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,
7881 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
7882 ret.insert(ret.end(),conn,conn+15);
7885 case INTERP_KERNEL::NORM_QUAD8:
7888 connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
7889 connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
7890 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
7892 ret.insert(ret.end(),conn,conn+20);
7895 case INTERP_KERNEL::NORM_POLYGON:
7897 std::back_insert_iterator< std::vector<int> > ii(ret);
7898 std::copy(connBg+1,connEnd,ii);
7900 std::reverse_iterator<const int *> rConnBg(connEnd);
7901 std::reverse_iterator<const int *> rConnEnd(connBg+1);
7902 std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
7903 std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
7904 for(std::size_t i=0;i<nbOfRadFaces;i++)
7907 int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
7908 std::copy(conn,conn+4,ii);
7913 throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
7918 * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
7920 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
7923 double v[3]={0.,0.,0.};
7924 std::size_t sz=std::distance(begin,end);
7929 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];
7930 v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
7931 v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
7933 double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
7935 // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
7936 // SEG3 forming a circle):
7937 if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
7939 v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
7940 for(std::size_t j=0;j<sz;j++)
7942 if (j%2) // current point i is quadratic, next point i+1 is standard
7945 ip1 = (j+1)%sz; // ip1 = "i+1"
7947 else // current point i is standard, next point i+1 is quadratic
7952 v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
7953 v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
7954 v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
7956 ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
7962 * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
7964 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
7966 std::vector<std::pair<int,int> > edges;
7967 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7968 const int *bgFace=begin;
7969 for(std::size_t i=0;i<nbOfFaces;i++)
7971 const int *endFace=std::find(bgFace+1,end,-1);
7972 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7973 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7975 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7976 if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
7978 edges.push_back(p1);
7982 return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
7986 * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
7988 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
7990 double vec0[3],vec1[3];
7991 std::size_t sz=std::distance(begin,end);
7993 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
7994 int nbOfNodes=(int)sz/2;
7995 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
7996 const double *pt0=coords+3*begin[0];
7997 const double *pt1=coords+3*begin[nbOfNodes];
7998 vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
7999 return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8002 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8004 std::size_t sz=std::distance(begin,end);
8005 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8006 std::size_t nbOfNodes(sz/2);
8007 std::copy(begin,end,(int *)tmp);
8008 for(std::size_t j=1;j<nbOfNodes;j++)
8010 begin[j]=tmp[nbOfNodes-j];
8011 begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8015 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8017 std::size_t sz=std::distance(begin,end);
8019 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8020 double vec0[3],vec1[3];
8021 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8022 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];
8023 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;
8026 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8028 std::size_t sz=std::distance(begin,end);
8030 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8032 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8033 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8034 return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8038 * 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 )
8039 * 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
8042 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8043 * \param [in] coords the coordinates with nb of components exactly equal to 3
8044 * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8045 * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8046 * \param [out] res the result is put at the end of the vector without any alteration of the data.
8048 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8050 int nbFaces=std::count(begin+1,end,-1)+1;
8051 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8052 double *vPtr=v->getPointer();
8053 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8054 double *pPtr=p->getPointer();
8055 const int *stFaceConn=begin+1;
8056 for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8058 const int *endFaceConn=std::find(stFaceConn,end,-1);
8059 ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8060 stFaceConn=endFaceConn+1;
8062 pPtr=p->getPointer(); vPtr=v->getPointer();
8063 DataArrayInt *comm1=0,*commI1=0;
8064 v->findCommonTuples(eps,-1,comm1,commI1);
8065 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8066 const int *comm1Ptr=comm1->getConstPointer();
8067 const int *commI1Ptr=commI1->getConstPointer();
8068 int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8069 res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8071 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8072 mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8073 mm->finishInsertingCells();
8075 for(int i=0;i<nbOfGrps1;i++)
8077 int vecId=comm1Ptr[commI1Ptr[i]];
8078 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8079 DataArrayInt *comm2=0,*commI2=0;
8080 tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8081 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8082 const int *comm2Ptr=comm2->getConstPointer();
8083 const int *commI2Ptr=commI2->getConstPointer();
8084 int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8085 for(int j=0;j<nbOfGrps2;j++)
8087 if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8089 res->insertAtTheEnd(begin,end);
8090 res->pushBackSilent(-1);
8094 int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8095 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8096 ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8097 DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8098 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8099 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8100 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8101 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8102 const int *idsNodePtr=idsNode->getConstPointer();
8103 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];
8104 double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8105 double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8106 if(std::abs(norm)>eps)
8108 double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8109 mm3->rotate(center,vec,angle);
8111 mm3->changeSpaceDimension(2);
8112 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8113 const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8114 const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8115 int nbOfCells=mm4->getNumberOfCells();
8116 for(int k=0;k<nbOfCells;k++)
8119 for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8120 res->pushBackSilent(idsNodePtr[*work]);
8121 res->pushBackSilent(-1);
8126 res->popBackSilent();
8130 * 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
8131 * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8133 * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8134 * \param [in] coords coordinates expected to have 3 components.
8135 * \param [in] begin start of the nodal connectivity of the face.
8136 * \param [in] end end of the nodal connectivity (excluded) of the face.
8137 * \param [out] v the normalized vector of size 3
8138 * \param [out] p the pos of plane
8140 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8142 std::size_t nbPoints=std::distance(begin,end);
8144 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8145 double vec[3]={0.,0.,0.};
8147 bool refFound=false;
8148 for(;j<nbPoints-1 && !refFound;j++)
8150 vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8151 vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8152 vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8153 double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8157 vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8160 for(std::size_t i=j;i<nbPoints-1;i++)
8163 curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8164 curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8165 curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8166 double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8169 curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8170 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];
8171 norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8174 v[0]/=norm; v[1]/=norm; v[2]/=norm;
8175 *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8179 throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8183 * This method tries to obtain a well oriented polyhedron.
8184 * If the algorithm fails, an exception will be thrown.
8186 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8188 std::list< std::pair<int,int> > edgesOK,edgesFinished;
8189 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8190 std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8192 int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8193 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8194 for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8196 while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8199 std::size_t smthChanged=0;
8200 for(std::size_t i=0;i<nbOfFaces;i++)
8202 endFace=std::find(bgFace+1,end,-1);
8203 nbOfEdgesInFace=std::distance(bgFace,endFace);
8207 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8209 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8210 std::pair<int,int> p2(p1.second,p1.first);
8211 bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8212 bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8213 if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8218 std::reverse(bgFace+1,endFace);
8219 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8221 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8222 std::pair<int,int> p2(p1.second,p1.first);
8223 if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8224 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8225 if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8226 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8227 std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8228 if(it!=edgesOK.end())
8231 edgesFinished.push_back(p1);
8234 edgesOK.push_back(p1);
8241 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8243 if(!edgesOK.empty())
8244 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8245 if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8246 {//not lucky ! The first face was not correctly oriented : reorient all faces...
8248 for(std::size_t i=0;i<nbOfFaces;i++)
8250 endFace=std::find(bgFace+1,end,-1);
8251 std::reverse(bgFace+1,endFace);
8258 * This method makes the assumption spacedimension == meshdimension == 2.
8259 * This method works only for linear cells.
8261 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8263 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8265 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8266 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8267 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8268 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=m->zipCoordsTraducer();
8269 int nbOfNodesExpected=m->getNumberOfNodes();
8270 if(m->getNumberOfCells()!=nbOfNodesExpected)
8271 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part or a quadratic 2D mesh !");
8272 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(m->getNumberOfNodes());
8273 const int *n2oPtr=n2o->getConstPointer();
8274 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8275 m->getReverseNodalConnectivity(revNodal,revNodalI);
8276 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
8277 const int *nodalPtr=m->getNodalConnectivity()->getConstPointer();
8278 const int *nodalIPtr=m->getNodalConnectivityIndex()->getConstPointer();
8279 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodesExpected+1,1);
8280 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYGON;
8281 if(nbOfNodesExpected<1)
8284 int prevNode=nodalPtr[nodalIPtr[0]+1];
8285 *work++=n2oPtr[prevNode];
8286 for(int i=1;i<nbOfNodesExpected;i++)
8288 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8290 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8291 conn.erase(prevNode);
8294 int curNode=*(conn.begin());
8295 *work++=n2oPtr[curNode];
8296 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8297 shar.erase(prevCell);
8300 prevCell=*(shar.begin());
8304 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 2 !");
8307 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 1 !");
8310 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected cell !");
8316 * This method makes the assumption spacedimension == meshdimension == 3.
8317 * This method works only for linear cells.
8319 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8321 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8323 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8324 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8325 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8326 const int *conn=m->getNodalConnectivity()->getConstPointer();
8327 const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8328 int nbOfCells=m->getNumberOfCells();
8329 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8330 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED;
8333 work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8334 for(int i=1;i<nbOfCells;i++)
8337 work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8343 * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8344 * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8346 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8350 for(int i=0;i<nbOfNodesInCell;i++)
8351 w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8352 else if(spaceDim==2)
8354 for(int i=0;i<nbOfNodesInCell;i++)
8356 w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8361 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8364 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8366 int nbOfCells=getNumberOfCells();
8368 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8369 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};
8370 ofs << " <" << getVTKDataSetType() << ">\n";
8371 ofs << " <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8372 ofs << " <PointData>\n" << pointData << std::endl;
8373 ofs << " </PointData>\n";
8374 ofs << " <CellData>\n" << cellData << std::endl;
8375 ofs << " </CellData>\n";
8376 ofs << " <Points>\n";
8377 if(getSpaceDimension()==3)
8378 _coords->writeVTK(ofs,8,"Points",byteData);
8381 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8382 coo->writeVTK(ofs,8,"Points",byteData);
8384 ofs << " </Points>\n";
8385 ofs << " <Cells>\n";
8386 const int *cPtr=_nodal_connec->getConstPointer();
8387 const int *cIPtr=_nodal_connec_index->getConstPointer();
8388 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8389 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8390 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8391 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8392 int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8393 int szFaceOffsets=0,szConn=0;
8394 for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8397 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8400 *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8401 w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8405 int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8406 *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8407 std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8408 *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8409 w4=std::copy(c.begin(),c.end(),w4);
8412 types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
8413 types->writeVTK(ofs,8,"UInt8","types",byteData);
8414 offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8415 if(szFaceOffsets!=0)
8416 {//presence of Polyhedra
8417 connectivity->reAlloc(szConn);
8418 faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8419 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8420 w1=faces->getPointer();
8421 for(int i=0;i<nbOfCells;i++)
8422 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8424 int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8426 const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8427 for(int j=0;j<nbFaces;j++)
8429 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8430 *w1++=(int)std::distance(w6,w5);
8431 w1=std::copy(w6,w5,w1);
8435 faces->writeVTK(ofs,8,"Int32","faces",byteData);
8437 connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8438 ofs << " </Cells>\n";
8439 ofs << " </Piece>\n";
8440 ofs << " </" << getVTKDataSetType() << ">\n";
8443 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8445 stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8447 { stream << " Not set !"; return ; }
8448 stream << " Mesh dimension : " << _mesh_dim << ".";
8452 { stream << " No coordinates set !"; return ; }
8453 if(!_coords->isAllocated())
8454 { stream << " Coordinates set but not allocated !"; return ; }
8455 stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8456 stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8457 if(!_nodal_connec_index)
8458 { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8459 if(!_nodal_connec_index->isAllocated())
8460 { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8461 int lgth=_nodal_connec_index->getNumberOfTuples();
8462 int cpt=_nodal_connec_index->getNumberOfComponents();
8463 if(cpt!=1 || lgth<1)
8465 stream << std::endl << "Number of cells : " << lgth-1 << ".";
8468 std::string MEDCouplingUMesh::getVTKDataSetType() const
8470 return std::string("UnstructuredGrid");
8474 * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8475 * returns a result mesh constituted by polygons.
8476 * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8477 * all nodes from m2.
8478 * The meshes should be in 2D space. In
8479 * addition, returns two arrays mapping cells of the result mesh to cells of the input
8481 * \param [in] m1 - the first input mesh which is a partitioned object.
8482 * \param [in] m2 - the second input mesh which is a partition tool.
8483 * \param [in] eps - precision used to detect coincident mesh entities.
8484 * \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8485 * cell an id of the cell of \a m1 it comes from. The caller is to delete
8486 * this array using decrRef() as it is no more needed.
8487 * \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8488 * cell an id of the cell of \a m2 it comes from. -1 value means that a
8489 * result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8490 * any cell of \a m2. The caller is to delete this array using decrRef() as
8491 * it is no more needed.
8492 * \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8493 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8494 * is no more needed.
8495 * \throw If the coordinates array is not set in any of the meshes.
8496 * \throw If the nodal connectivity of cells is not defined in any of the meshes.
8497 * \throw If any of the meshes is not a 2D mesh in 2D space.
8499 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8500 double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8502 m1->checkFullyDefined();
8503 m2->checkFullyDefined();
8504 if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8505 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!");
8507 // Step 1: compute all edge intersections (new nodes)
8508 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8509 MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
8510 DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8511 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
8512 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8513 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8514 IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
8515 m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8516 addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
8517 revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8518 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8519 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8521 // Step 2: re-order newly created nodes according to the ordering found in m2
8522 std::vector< std::vector<int> > intersectEdge2;
8523 BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8524 subDiv2.clear(); dd5=0; dd6=0;
8527 std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8528 std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8529 BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8530 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8532 // Step 4: Prepare final result:
8533 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
8534 addCooDa->alloc((int)(addCoo.size())/2,2);
8535 std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8536 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
8537 addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8538 std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8539 std::vector<const DataArrayDouble *> coordss(4);
8540 coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8541 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
8542 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
8543 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8544 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8545 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8546 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8547 ret->setConnectivity(conn,connI,true);
8548 ret->setCoords(coo);
8549 cellNb1=c1.retn(); cellNb2=c2.retn();
8555 * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
8556 * (newly created) nodes corresponding to the edge intersections.
8558 * @param[out] cr, crI connectivity of the resulting mesh
8559 * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
8560 * TODO: describe input parameters
8562 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8563 const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8564 const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8565 const std::vector<double>& addCoords,
8566 std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8568 static const int SPACEDIM=2;
8569 const double *coo1=m1->getCoords()->getConstPointer();
8570 const int *conn1=m1->getNodalConnectivity()->getConstPointer();
8571 const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
8572 int offset1=m1->getNumberOfNodes();
8573 const double *coo2=m2->getCoords()->getConstPointer();
8574 const int *conn2=m2->getNodalConnectivity()->getConstPointer();
8575 const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
8576 int offset2=offset1+m2->getNumberOfNodes();
8577 int offset3=offset2+((int)addCoords.size())/2;
8578 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
8579 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
8580 // Here a BBTree on 2D-cells, not on segments:
8581 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
8582 int ncell1=m1->getNumberOfCells();
8584 for(int i=0;i<ncell1;i++)
8586 std::vector<int> candidates2;
8587 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
8588 std::map<INTERP_KERNEL::Node *,int> mapp;
8589 std::map<int,INTERP_KERNEL::Node *> mappRev;
8590 INTERP_KERNEL::QuadraticPolygon pol1;
8591 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8592 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8593 // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
8594 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8595 // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
8596 pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8597 desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8599 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
8600 std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8601 INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8602 for(it1.first();!it1.finished();it1.next())
8603 edges1.insert(it1.current()->getPtr());
8605 std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
8606 std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8608 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8610 INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8611 const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8612 // Complete mapping with elements coming from the current cell it2 in mesh2:
8613 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8614 // pol2 is the new QP in the final merged result.
8615 pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8616 pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
8619 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8621 pol1.initLocationsWithOther(pol2s[ii]);
8622 pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8623 //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8624 pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8626 // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
8627 // by m2 but that we still want to keep in the final result.
8632 INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8634 catch(INTERP_KERNEL::Exception& e)
8636 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();
8637 throw INTERP_KERNEL::Exception(oss.str().c_str());
8640 for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8641 (*it).second->decrRef();
8646 * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
8647 * It builds the descending connectivity of the two meshes, and then using a binary tree
8648 * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
8649 * Documentation about parameters colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
8651 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
8652 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
8653 MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
8654 std::vector<double>& addCoo,
8655 MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
8656 throw(INTERP_KERNEL::Exception)
8658 static const int SPACEDIM=2;
8659 // Build desc connectivity
8660 desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
8661 desc2=DataArrayInt::New();
8662 descIndx2=DataArrayInt::New();
8663 revDesc2=DataArrayInt::New();
8664 revDescIndx2=DataArrayInt::New();
8665 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
8666 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
8667 m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
8668 m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
8669 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
8670 const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
8671 const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
8673 // Build BB tree of all edges in the tool mesh (second mesh)
8674 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
8675 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
8676 int nDescCell1=m1Desc->getNumberOfCells();
8677 int nDescCell2=m2Desc->getNumberOfCells();
8678 intersectEdge1.resize(nDescCell1);
8679 colinear2.resize(nDescCell2);
8680 subDiv2.resize(nDescCell2);
8681 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
8683 std::vector<int> candidates1(1);
8684 int offset1=m1->getNumberOfNodes();
8685 int offset2=offset1+m2->getNumberOfNodes();
8686 for(int i=0;i<nDescCell1;i++) // for all edges in the first mesh
8688 std::vector<int> candidates2; // edges of mesh2 candidate for intersection
8689 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
8690 if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
8692 std::map<INTERP_KERNEL::Node *,int> map1,map2;
8693 // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
8694 INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
8696 INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
8697 // 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
8698 // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
8699 std::set<INTERP_KERNEL::Node *> nodes;
8700 pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
8701 std::size_t szz(nodes.size());
8702 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
8703 std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
8704 for(std::size_t iii=0;iii<szz;iii++,itt++)
8705 { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
8706 // end of protection
8707 // Performs egde cutting:
8708 pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
8713 intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
8715 m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
8716 m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
8720 * This method performs the 2nd step of Partition of 2D mesh.
8721 * This method has 4 inputs :
8722 * - a mesh 'm1' with meshDim==1 and a SpaceDim==2
8723 * - a mesh 'm2' with meshDim==1 and a SpaceDim==2
8724 * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
8725 * 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'
8726 * Nodes end up lying consecutively on a cutted edge.
8727 * \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.
8728 * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
8729 * \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.
8730 * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
8731 * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
8733 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8734 const std::vector<double>& addCoo,
8735 const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
8737 int offset1=m1->getNumberOfNodes();
8738 int ncell=m2->getNumberOfCells();
8739 const int *c=m2->getNodalConnectivity()->getConstPointer();
8740 const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
8741 const double *coo=m2->getCoords()->getConstPointer();
8742 const double *cooBis=m1->getCoords()->getConstPointer();
8743 int offset2=offset1+m2->getNumberOfNodes();
8744 intersectEdge.resize(ncell);
8745 for(int i=0;i<ncell;i++,cI++)
8747 const std::vector<int>& divs=subDiv[i];
8748 int nnode=cI[1]-cI[0]-1;
8749 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
8750 std::map<INTERP_KERNEL::Node *, int> mapp22;
8751 for(int j=0;j<nnode;j++)
8753 INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
8754 int nnid=c[(*cI)+j+1];
8755 mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
8756 mapp22[nn]=nnid+offset1;
8758 INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
8759 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
8760 ((*it).second.first)->decrRef();
8761 std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
8762 std::map<INTERP_KERNEL::Node *,int> mapp3;
8763 for(std::size_t j=0;j<divs.size();j++)
8766 INTERP_KERNEL::Node *tmp=0;
8768 tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
8770 tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
8772 tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
8776 e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
8777 for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
8784 * 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).
8785 * 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
8786 * with a plane. The result will be put in 'cut3DSuf' out parameter.
8787 * \param [in] cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
8788 * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
8789 * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
8790 * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
8791 * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
8792 * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
8793 * \param [in] desc is the descending connectivity 3DSurf->3DCurve
8794 * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
8795 * \param [out] cut3DSuf input/output param.
8797 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
8798 const int *nodal3DCurve, const int *nodalIndx3DCurve,
8799 const int *desc, const int *descIndx,
8800 std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
8802 std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
8803 int nbOf3DSurfCell=(int)cut3DSurf.size();
8804 for(int i=0;i<nbOf3DSurfCell;i++)
8806 std::vector<int> res;
8807 int offset=descIndx[i];
8808 int nbOfSeg=descIndx[i+1]-offset;
8809 for(int j=0;j<nbOfSeg;j++)
8811 int edgeId=desc[offset+j];
8812 int status=cut3DCurve[edgeId];
8816 res.push_back(status);
8819 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
8820 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
8828 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8834 std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
8835 std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
8838 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8842 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
8847 {// case when plane is on a multi colinear edge of a polyhedron
8848 if((int)res.size()==2*nbOfSeg)
8850 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
8853 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
8860 * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
8861 * 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).
8862 * 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
8863 * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
8864 * \param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
8865 * \param desc is the descending connectivity 3D->3DSurf
8866 * \param descIndx is the descending connectivity index 3D->3DSurf
8868 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
8869 const int *desc, const int *descIndx,
8870 DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
8872 checkFullyDefined();
8873 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8874 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
8875 const int *nodal3D=_nodal_connec->getConstPointer();
8876 const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
8877 int nbOfCells=getNumberOfCells();
8878 for(int i=0;i<nbOfCells;i++)
8880 std::map<int, std::set<int> > m;
8881 int offset=descIndx[i];
8882 int nbOfFaces=descIndx[i+1]-offset;
8885 for(int j=0;j<nbOfFaces;j++)
8887 const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
8888 if(p.first!=-1 && p.second!=-1)
8892 start=p.first; end=p.second;
8893 m[p.first].insert(p.second);
8894 m[p.second].insert(p.first);
8898 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
8899 int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
8900 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8901 INTERP_KERNEL::NormalizedCellType cmsId;
8902 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
8903 start=tmp[0]; end=tmp[nbOfNodesSon-1];
8904 for(unsigned k=0;k<nbOfNodesSon;k++)
8906 m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
8907 m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
8914 std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
8918 std::map<int, std::set<int> >::const_iterator it=m.find(start);
8919 const std::set<int>& s=(*it).second;
8920 std::set<int> s2; s2.insert(prev);
8922 std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
8925 int val=*s3.begin();
8926 conn.push_back(start);
8933 conn.push_back(end);
8936 nodalRes->insertAtTheEnd(conn.begin(),conn.end());
8937 nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
8938 cellIds->pushBackSilent(i);
8944 * 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
8945 * 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
8946 * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
8947 * 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
8948 * 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.
8950 * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
8952 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
8954 std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
8957 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
8958 if(cm.getDimension()==2)
8960 const int *node=nodalConnBg+1;
8961 int startNode=*node++;
8962 double refX=coords[2*startNode];
8963 for(;node!=nodalConnEnd;node++)
8965 if(coords[2*(*node)]<refX)
8968 refX=coords[2*startNode];
8971 std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
8975 double angle0=-M_PI/2;
8980 double angleNext=0.;
8981 while(nextNode!=startNode)
8985 for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
8987 if(*node!=tmpOut.back() && *node!=prevNode)
8989 tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
8990 double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
8995 res=angle0-angleM+2.*M_PI;
9004 if(nextNode!=startNode)
9006 angle0=angleNext-M_PI;
9009 prevNode=tmpOut.back();
9010 tmpOut.push_back(nextNode);
9013 std::vector<int> tmp3(2*(sz-1));
9014 std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
9015 std::copy(nodalConnBg+1,nodalConnEnd,it);
9016 if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
9018 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
9021 if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
9023 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
9028 nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
9029 nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
9034 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
9037 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
9041 * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
9042 * 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.
9044 * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
9045 * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
9046 * \param [in,out] arr array in which the remove operation will be done.
9047 * \param [in,out] arrIndx array in the remove operation will modify
9048 * \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])
9049 * \return true if \b arr and \b arrIndx have been modified, false if not.
9051 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
9053 if(!arrIndx || !arr)
9054 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
9055 if(offsetForRemoval<0)
9056 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
9057 std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
9058 int nbOfGrps=arrIndx->getNumberOfTuples()-1;
9059 int *arrIPtr=arrIndx->getPointer();
9062 const int *arrPtr=arr->getConstPointer();
9063 std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
9064 for(int i=0;i<nbOfGrps;i++,arrIPtr++)
9066 if(*arrIPtr-previousArrI>offsetForRemoval)
9068 for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
9070 if(s.find(*work)==s.end())
9071 arrOut.push_back(*work);
9074 previousArrI=*arrIPtr;
9075 *arrIPtr=(int)arrOut.size();
9077 if(arr->getNumberOfTuples()==(int)arrOut.size())
9079 arr->alloc((int)arrOut.size(),1);
9080 std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
9085 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9086 * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
9087 * The selection of extraction is done standardly in new2old format.
9088 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
9090 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9091 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9092 * \param [in] arrIn arr origin array from which the extraction will be done.
9093 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9094 * \param [out] arrOut the resulting array
9095 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9096 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
9098 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9099 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9101 if(!arrIn || !arrIndxIn)
9102 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
9103 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
9104 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
9105 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
9106 std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
9107 const int *arrInPtr=arrIn->getConstPointer();
9108 const int *arrIndxPtr=arrIndxIn->getConstPointer();
9109 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
9111 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
9112 int maxSizeOfArr=arrIn->getNumberOfTuples();
9113 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9114 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9115 arrIo->alloc((int)(sz+1),1);
9116 const int *idsIt=idsOfSelectBg;
9117 int *work=arrIo->getPointer();
9120 for(std::size_t i=0;i<sz;i++,work++,idsIt++)
9122 if(*idsIt>=0 && *idsIt<nbOfGrps)
9123 lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
9126 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
9127 throw INTERP_KERNEL::Exception(oss.str().c_str());
9133 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
9134 oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
9135 throw INTERP_KERNEL::Exception(oss.str().c_str());
9138 arro->alloc(lgth,1);
9139 work=arro->getPointer();
9140 idsIt=idsOfSelectBg;
9141 for(std::size_t i=0;i<sz;i++,idsIt++)
9143 if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
9144 work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
9147 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
9148 oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
9149 throw INTERP_KERNEL::Exception(oss.str().c_str());
9153 arrIndexOut=arrIo.retn();
9157 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9158 * 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 ).
9159 * The selection of extraction is done standardly in new2old format.
9160 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
9162 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9163 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9164 * \param [in] arrIn arr origin array from which the extraction will be done.
9165 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9166 * \param [out] arrOut the resulting array
9167 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9168 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
9170 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9171 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9173 if(!arrIn || !arrIndxIn)
9174 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
9175 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
9176 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
9177 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
9178 int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
9179 const int *arrInPtr=arrIn->getConstPointer();
9180 const int *arrIndxPtr=arrIndxIn->getConstPointer();
9181 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
9183 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
9184 int maxSizeOfArr=arrIn->getNumberOfTuples();
9185 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9186 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9187 arrIo->alloc((int)(sz+1),1);
9188 int idsIt=idsOfSelectStart;
9189 int *work=arrIo->getPointer();
9192 for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
9194 if(idsIt>=0 && idsIt<nbOfGrps)
9195 lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
9198 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
9199 throw INTERP_KERNEL::Exception(oss.str().c_str());
9205 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
9206 oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
9207 throw INTERP_KERNEL::Exception(oss.str().c_str());
9210 arro->alloc(lgth,1);
9211 work=arro->getPointer();
9212 idsIt=idsOfSelectStart;
9213 for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
9215 if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
9216 work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
9219 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
9220 oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
9221 throw INTERP_KERNEL::Exception(oss.str().c_str());
9225 arrIndexOut=arrIo.retn();
9229 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9230 * 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
9231 * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9232 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9234 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9235 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9236 * \param [in] arrIn arr origin array from which the extraction will be done.
9237 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9238 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
9239 * \param [in] srcArrIndex index array of \b srcArr
9240 * \param [out] arrOut the resulting array
9241 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9243 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9245 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9246 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9247 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9249 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9250 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
9251 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9252 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9253 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9254 std::vector<bool> v(nbOfTuples,true);
9256 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9257 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9258 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
9260 if(*it>=0 && *it<nbOfTuples)
9263 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
9267 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
9268 throw INTERP_KERNEL::Exception(oss.str().c_str());
9271 srcArrIndexPtr=srcArrIndex->getConstPointer();
9272 arrIo->alloc(nbOfTuples+1,1);
9273 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9274 const int *arrInPtr=arrIn->getConstPointer();
9275 const int *srcArrPtr=srcArr->getConstPointer();
9276 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9277 int *arroPtr=arro->getPointer();
9278 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9282 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9283 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9287 std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
9288 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9289 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9293 arrIndexOut=arrIo.retn();
9297 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9298 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9300 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9301 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9302 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9303 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9304 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
9305 * \param [in] srcArrIndex index array of \b srcArr
9307 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
9309 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9310 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9312 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9313 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
9314 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9315 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9316 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9317 int *arrInOutPtr=arrInOut->getPointer();
9318 const int *srcArrPtr=srcArr->getConstPointer();
9319 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
9321 if(*it>=0 && *it<nbOfTuples)
9323 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
9324 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
9327 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] !";
9328 throw INTERP_KERNEL::Exception(oss.str().c_str());
9333 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
9334 throw INTERP_KERNEL::Exception(oss.str().c_str());
9340 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9341 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9342 * 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]].
9343 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9344 * A negative value in \b arrIn means that it is ignored.
9345 * 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.
9347 * \param [in] arrIn arr origin array from which the extraction will be done.
9348 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9349 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9350 * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
9352 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
9354 int seed=0,nbOfDepthPeelingPerformed=0;
9355 return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
9359 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9360 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9361 * 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]].
9362 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9363 * A negative value in \b arrIn means that it is ignored.
9364 * 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.
9365 * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
9366 * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
9367 * \param [in] arrIn arr origin array from which the extraction will be done.
9368 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9369 * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
9370 * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
9371 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9372 * \sa MEDCouplingUMesh::partitionBySpreadZone
9374 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
9376 nbOfDepthPeelingPerformed=0;
9378 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
9379 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9382 DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
9386 std::vector<bool> fetched(nbOfTuples,false);
9387 return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
9390 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
9392 nbOfDepthPeelingPerformed=0;
9393 if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
9394 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
9395 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9396 std::vector<bool> fetched2(nbOfTuples,false);
9398 for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
9400 if(*seedElt>=0 && *seedElt<nbOfTuples)
9401 { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
9403 { 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()); }
9405 const int *arrInPtr=arrIn->getConstPointer();
9406 const int *arrIndxPtr=arrIndxIn->getConstPointer();
9407 int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
9408 std::vector<int> idsToFetch1(seedBg,seedEnd);
9409 std::vector<int> idsToFetch2;
9410 std::vector<int> *idsToFetch=&idsToFetch1;
9411 std::vector<int> *idsToFetchOther=&idsToFetch2;
9412 while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
9414 for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
9415 for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
9417 { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
9418 std::swap(idsToFetch,idsToFetchOther);
9419 idsToFetchOther->clear();
9420 nbOfDepthPeelingPerformed++;
9422 int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
9424 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
9425 int *retPtr=ret->getPointer();
9426 for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
9433 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9434 * 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
9435 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9436 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9438 * \param [in] start begin of set of ids of the input extraction (included)
9439 * \param [in] end end of set of ids of the input extraction (excluded)
9440 * \param [in] step step of the set of ids in range mode.
9441 * \param [in] arrIn arr origin array from which the extraction will be done.
9442 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9443 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9444 * \param [in] srcArrIndex index array of \b srcArr
9445 * \param [out] arrOut the resulting array
9446 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9448 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
9450 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9451 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9452 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9454 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9455 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
9456 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9457 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9458 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9460 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9461 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9462 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
9464 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9466 if(it>=0 && it<nbOfTuples)
9467 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
9470 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9471 throw INTERP_KERNEL::Exception(oss.str().c_str());
9474 srcArrIndexPtr=srcArrIndex->getConstPointer();
9475 arrIo->alloc(nbOfTuples+1,1);
9476 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9477 const int *arrInPtr=arrIn->getConstPointer();
9478 const int *srcArrPtr=srcArr->getConstPointer();
9479 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9480 int *arroPtr=arro->getPointer();
9481 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9483 int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
9486 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9487 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9491 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9492 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9496 arrIndexOut=arrIo.retn();
9500 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9501 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9503 * \param [in] start begin of set of ids of the input extraction (included)
9504 * \param [in] end end of set of ids of the input extraction (excluded)
9505 * \param [in] step step of the set of ids in range mode.
9506 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9507 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9508 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9509 * \param [in] srcArrIndex index array of \b srcArr
9511 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9513 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9514 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9516 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9517 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
9518 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9519 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9520 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9521 int *arrInOutPtr=arrInOut->getPointer();
9522 const int *srcArrPtr=srcArr->getConstPointer();
9523 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
9525 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9527 if(it>=0 && it<nbOfTuples)
9529 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
9530 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
9533 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9534 throw INTERP_KERNEL::Exception(oss.str().c_str());
9539 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9540 throw INTERP_KERNEL::Exception(oss.str().c_str());
9546 * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
9547 * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
9548 * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
9549 * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
9550 * The sum of measure field of returned mesh is equal to the sum of measure field of this.
9552 * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
9554 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
9556 checkFullyDefined();
9557 int mdim=getMeshDimension();
9558 int spaceDim=getSpaceDimension();
9560 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
9561 std::vector<DataArrayInt *> partition=partitionBySpreadZone();
9562 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
9563 std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
9564 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
9565 ret->setCoords(getCoords());
9566 ret->allocateCells((int)partition.size());
9568 for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
9570 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
9571 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
9575 cell=tmp->buildUnionOf2DMesh();
9578 cell=tmp->buildUnionOf3DMesh();
9581 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
9584 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
9587 ret->finishInsertingCells();
9592 * This method partitions \b this into contiguous zone.
9593 * This method only needs a well defined connectivity. Coordinates are not considered here.
9594 * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
9596 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
9598 int nbOfCellsCur=getNumberOfCells();
9599 std::vector<DataArrayInt *> ret;
9602 DataArrayInt *neigh=0,*neighI=0;
9603 computeNeighborsOfCells(neigh,neighI);
9604 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9605 std::vector<bool> fetchedCells(nbOfCellsCur,false);
9606 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9608 while(seed<nbOfCellsCur)
9610 int nbOfPeelPerformed=0;
9611 ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
9612 seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
9614 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
9615 ret.push_back((*it).retn());
9620 * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
9621 * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
9623 * \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.
9624 * \return a newly allocated DataArrayInt to be managed by the caller.
9625 * \throw In case of \a code has not the right format (typically of size 3*n)
9627 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
9629 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
9630 std::size_t nb=code.size()/3;
9631 if(code.size()%3!=0)
9632 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
9633 ret->alloc((int)nb,2);
9634 int *retPtr=ret->getPointer();
9635 for(std::size_t i=0;i<nb;i++,retPtr+=2)
9637 retPtr[0]=code[3*i+2];
9638 retPtr[1]=code[3*i+2]+code[3*i+1];
9644 * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
9645 * All cells in \a this are expected to be linear 3D cells.
9646 * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
9647 * It leads to an increase to number of cells.
9648 * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
9649 * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints
9650 * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
9652 * \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.
9653 * For all other cells, the splitting policy will be ignored.
9654 * \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.
9655 * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
9656 * an id of old cell producing it. The caller is to delete this array using
9657 * decrRef() as it is no more needed.
9658 * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
9660 * \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
9661 * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
9663 * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
9664 * \throw If \a this is not fully constituted with linear 3D cells.
9665 * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
9667 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
9669 INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
9670 checkConnectivityFullyDefined();
9671 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
9672 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
9673 int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
9674 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
9675 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
9676 int *retPt(ret->getPointer());
9677 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
9678 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
9679 const int *oldc(_nodal_connec->begin());
9680 const int *oldci(_nodal_connec_index->begin());
9681 const double *coords(_coords->begin());
9682 for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
9684 std::vector<int> a; std::vector<double> b;
9685 INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
9686 std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
9687 const int *aa(&a[0]);
9690 for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
9692 *it=(-(*(it))-1+nbNodes);
9693 addPts->insertAtTheEnd(b.begin(),b.end());
9694 nbNodes+=(int)b.size()/3;
9696 for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
9697 newConn->insertAtTheEnd(aa,aa+4);
9699 if(!addPts->empty())
9701 addPts->rearrange(3);
9702 nbOfAdditionalPoints=addPts->getNumberOfTuples();
9703 addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
9704 ret0->setCoords(addPts);
9708 nbOfAdditionalPoints=0;
9709 ret0->setCoords(getCoords());
9711 ret0->setNodalConnectivity(newConn);
9713 ret->computeOffsets2();
9714 n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
9718 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
9719 _own_cell(true),_cell_id(-1),_nb_cell(0)
9724 _nb_cell=mesh->getNumberOfCells();
9728 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
9736 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
9737 _own_cell(false),_cell_id(bg-1),
9744 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
9747 if(_cell_id<_nb_cell)
9756 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
9762 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
9764 return new MEDCouplingUMeshCellByTypeIterator(_mesh);
9767 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
9773 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
9781 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
9787 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
9792 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
9797 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
9799 return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
9802 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
9807 _nb_cell=mesh->getNumberOfCells();
9811 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
9818 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
9820 const int *c=_mesh->getNodalConnectivity()->getConstPointer();
9821 const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
9822 if(_cell_id<_nb_cell)
9824 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
9825 int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
9826 int startId=_cell_id;
9827 _cell_id+=nbOfElems;
9828 return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
9834 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
9838 _conn=mesh->getNodalConnectivity()->getPointer();
9839 _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
9843 void MEDCouplingUMeshCell::next()
9845 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9850 _conn_lgth=_conn_indx[1]-_conn_indx[0];
9853 std::string MEDCouplingUMeshCell::repr() const
9855 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9857 std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
9859 std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
9863 return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
9866 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
9868 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9869 return (INTERP_KERNEL::NormalizedCellType)_conn[0];
9871 return INTERP_KERNEL::NORM_ERROR;
9874 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
9877 if(_conn_lgth!=NOTICABLE_FIRST_VAL)