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 const int *connOld(_nodal_connec->getConstPointer());
1045 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1046 std::vector<bool> toBeDone(nbOfCells,false);
1047 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1049 if(*iter>=0 && *iter<nbOfCells)
1050 toBeDone[*iter]=true;
1053 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1054 oss << " in range [0," << nbOfCells << ") !";
1055 throw INTERP_KERNEL::Exception(oss.str().c_str());
1058 for(int cellId=0;cellId<nbOfCells;cellId++)
1060 int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1061 int lgthOld(posP1-pos-1);
1062 if(toBeDone[cellId])
1064 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1065 unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1066 int *tmp(new int[nbOfFaces*lgthOld+1]);
1067 int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1068 for(unsigned j=0;j<nbOfFaces;j++)
1070 INTERP_KERNEL::NormalizedCellType type;
1071 unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1075 std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1076 connNew->pushBackValsSilent(tmp,tmp+newLgth);
1077 connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1082 connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1083 connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1086 setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1092 * Converts all cells to either polygons (if \a this is a 2D mesh) or
1093 * polyhedrons (if \a this is a 3D mesh).
1094 * \warning As this method is purely for user-friendliness and no optimization is
1095 * done to avoid construction of a useless vector, this method can be costly
1097 * \throw If the coordinates array is not set.
1098 * \throw If the nodal connectivity of cells is node defined.
1099 * \throw If dimension of \a this mesh is not either 2 or 3.
1101 void MEDCouplingUMesh::convertAllToPoly()
1103 int nbOfCells=getNumberOfCells();
1104 std::vector<int> cellIds(nbOfCells);
1105 for(int i=0;i<nbOfCells;i++)
1107 convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1111 * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1112 * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1113 * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1114 * base facet of the volume and the second half of nodes describes an opposite facet
1115 * having the same number of nodes as the base one. This method converts such
1116 * connectivity to a valid polyhedral format where connectivity of each facet is
1117 * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1118 * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1119 * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1120 * a correct orientation of the first facet of a polyhedron, else orientation of a
1121 * corrected cell is reverse.<br>
1122 * This method is useful to build an extruded unstructured mesh with polyhedrons as
1123 * it releases the user from boring description of polyhedra connectivity in the valid
1125 * \throw If \a this->getMeshDimension() != 3.
1126 * \throw If \a this->getSpaceDimension() != 3.
1127 * \throw If the nodal connectivity of cells is not defined.
1128 * \throw If the coordinates array is not set.
1129 * \throw If \a this mesh contains polyhedrons with the valid connectivity.
1130 * \throw If \a this mesh contains polyhedrons with odd number of nodes.
1132 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1133 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1135 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1137 checkFullyDefined();
1138 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1139 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1140 int nbOfCells=getNumberOfCells();
1141 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1142 newCi->alloc(nbOfCells+1,1);
1143 int *newci=newCi->getPointer();
1144 const int *ci=_nodal_connec_index->getConstPointer();
1145 const int *c=_nodal_connec->getConstPointer();
1147 for(int i=0;i<nbOfCells;i++)
1149 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1150 if(type==INTERP_KERNEL::NORM_POLYHED)
1152 if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1154 std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1155 throw INTERP_KERNEL::Exception(oss.str().c_str());
1157 std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1160 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 !";
1161 throw INTERP_KERNEL::Exception(oss.str().c_str());
1164 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)
1167 newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1169 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1170 newC->alloc(newci[nbOfCells],1);
1171 int *newc=newC->getPointer();
1172 for(int i=0;i<nbOfCells;i++)
1174 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1175 if(type==INTERP_KERNEL::NORM_POLYHED)
1177 std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1178 newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1180 for(std::size_t j=0;j<n1;j++)
1182 newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1184 newc[n1+5*j+1]=c[ci[i]+1+j];
1185 newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1186 newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1187 newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1192 newc=std::copy(c+ci[i],c+ci[i+1],newc);
1194 _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1195 _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1200 * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1201 * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1202 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1203 * to write this mesh to the MED file, its cells must be sorted using
1204 * sortCellsInMEDFileFrmt().
1205 * \return \c true if at least one cell has been converted, \c false else. In the
1206 * last case the nodal connectivity remains unchanged.
1207 * \throw If the coordinates array is not set.
1208 * \throw If the nodal connectivity of cells is not defined.
1209 * \throw If \a this->getMeshDimension() < 0.
1211 bool MEDCouplingUMesh::unPolyze()
1213 checkFullyDefined();
1214 int mdim=getMeshDimension();
1216 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1219 int nbOfCells=getNumberOfCells();
1222 int initMeshLgth=getMeshLength();
1223 int *conn=_nodal_connec->getPointer();
1224 int *index=_nodal_connec_index->getPointer();
1229 for(int i=0;i<nbOfCells;i++)
1231 lgthOfCurCell=index[i+1]-posOfCurCell;
1232 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1233 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1234 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1238 switch(cm.getDimension())
1242 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1243 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1244 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1249 int nbOfFaces,lgthOfPolyhConn;
1250 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1251 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1256 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1260 ret=ret || (newType!=type);
1261 conn[newPos]=newType;
1263 posOfCurCell=index[i+1];
1268 std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1269 newPos+=lgthOfCurCell;
1270 posOfCurCell+=lgthOfCurCell;
1274 if(newPos!=initMeshLgth)
1275 _nodal_connec->reAlloc(newPos);
1282 * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1283 * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1284 * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells.
1286 * \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
1289 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1291 checkFullyDefined();
1292 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1293 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1294 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1295 coords->recenterForMaxPrecision(eps);
1297 int nbOfCells=getNumberOfCells();
1298 const int *conn=_nodal_connec->getConstPointer();
1299 const int *index=_nodal_connec_index->getConstPointer();
1300 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1301 connINew->alloc(nbOfCells+1,1);
1302 int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1303 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1305 for(int i=0;i<nbOfCells;i++,connINewPtr++)
1307 if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1309 SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1313 connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1314 *connINewPtr=connNew->getNumberOfTuples();
1317 setConnectivity(connNew,connINew,false);
1321 * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1322 * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1323 * the format of returned DataArrayInt instance.
1325 * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1326 * \sa MEDCouplingUMesh::getNodeIdsInUse
1328 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1330 checkConnectivityFullyDefined();
1331 int nbOfCells=getNumberOfCells();
1332 const int *connIndex=_nodal_connec_index->getConstPointer();
1333 const int *conn=_nodal_connec->getConstPointer();
1334 const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1335 int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1336 std::vector<bool> retS(maxElt,false);
1337 for(int i=0;i<nbOfCells;i++)
1338 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1342 for(int i=0;i<maxElt;i++)
1345 DataArrayInt *ret=DataArrayInt::New();
1347 int *retPtr=ret->getPointer();
1348 for(int i=0;i<maxElt;i++)
1355 * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1356 * \sa MEDCouplingUMesh::getNodeIdsInUse
1358 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1360 int nbOfNodes=(int)nodeIdsInUse.size();
1361 int nbOfCells=getNumberOfCells();
1362 const int *connIndex=_nodal_connec_index->getConstPointer();
1363 const int *conn=_nodal_connec->getConstPointer();
1364 for(int i=0;i<nbOfCells;i++)
1365 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1368 if(conn[j]<nbOfNodes)
1369 nodeIdsInUse[conn[j]]=true;
1372 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1373 throw INTERP_KERNEL::Exception(oss.str().c_str());
1379 * Finds nodes not used in any cell and returns an array giving a new id to every node
1380 * by excluding the unused nodes, for which the array holds -1. The result array is
1381 * a mapping in "Old to New" mode.
1382 * \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1383 * \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1384 * this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1385 * if the node is unused or a new id else. The caller is to delete this
1386 * array using decrRef() as it is no more needed.
1387 * \throw If the coordinates array is not set.
1388 * \throw If the nodal connectivity of cells is not defined.
1389 * \throw If the nodal connectivity includes an invalid id.
1391 * \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1392 * \ref py_mcumesh_getNodeIdsInUse "Here is a Python example".
1393 * \sa computeNodeIdsAlg()
1395 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1398 int nbOfNodes=getNumberOfNodes();
1399 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1400 ret->alloc(nbOfNodes,1);
1401 int *traducer=ret->getPointer();
1402 std::fill(traducer,traducer+nbOfNodes,-1);
1403 int nbOfCells=getNumberOfCells();
1404 const int *connIndex=_nodal_connec_index->getConstPointer();
1405 const int *conn=_nodal_connec->getConstPointer();
1406 for(int i=0;i<nbOfCells;i++)
1407 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1410 if(conn[j]<nbOfNodes)
1411 traducer[conn[j]]=1;
1414 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1415 throw INTERP_KERNEL::Exception(oss.str().c_str());
1418 nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1419 std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1424 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1425 * For each cell in \b this the number of nodes constituting cell is computed.
1426 * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1427 * So for pohyhedrons some nodes can be counted several times in the returned result.
1429 * \return a newly allocated array
1430 * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1432 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1434 checkConnectivityFullyDefined();
1435 int nbOfCells=getNumberOfCells();
1436 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1437 ret->alloc(nbOfCells,1);
1438 int *retPtr=ret->getPointer();
1439 const int *conn=getNodalConnectivity()->getConstPointer();
1440 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1441 for(int i=0;i<nbOfCells;i++,retPtr++)
1443 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1444 *retPtr=connI[i+1]-connI[i]-1;
1446 *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1452 * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1453 * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1455 * \return DataArrayInt * - new object to be deallocated by the caller.
1456 * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1458 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1460 checkConnectivityFullyDefined();
1461 int nbOfCells=getNumberOfCells();
1462 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1463 ret->alloc(nbOfCells,1);
1464 int *retPtr=ret->getPointer();
1465 const int *conn=getNodalConnectivity()->getConstPointer();
1466 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1467 for(int i=0;i<nbOfCells;i++,retPtr++)
1469 std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1470 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1471 *retPtr=(int)s.size();
1475 *retPtr=(int)s.size();
1482 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1483 * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1485 * \return a newly allocated array
1487 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1489 checkConnectivityFullyDefined();
1490 int nbOfCells=getNumberOfCells();
1491 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1492 ret->alloc(nbOfCells,1);
1493 int *retPtr=ret->getPointer();
1494 const int *conn=getNodalConnectivity()->getConstPointer();
1495 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1496 for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1498 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1499 *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1505 * Removes unused nodes (the node coordinates array is shorten) and returns an array
1506 * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1507 * array mean that the corresponding old node is no more used.
1508 * \return DataArrayInt * - a new instance of DataArrayInt of length \a
1509 * this->getNumberOfNodes() before call of this method. The caller is to
1510 * delete this array using decrRef() as it is no more needed.
1511 * \throw If the coordinates array is not set.
1512 * \throw If the nodal connectivity of cells is not defined.
1513 * \throw If the nodal connectivity includes an invalid id.
1515 * \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1516 * \ref py_mcumesh_zipCoordsTraducer "Here is a Python example".
1518 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1520 return MEDCouplingPointSet::zipCoordsTraducer();
1524 * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1525 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1527 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1532 return AreCellsEqual0(conn,connI,cell1,cell2);
1534 return AreCellsEqual1(conn,connI,cell1,cell2);
1536 return AreCellsEqual2(conn,connI,cell1,cell2);
1538 return AreCellsEqual3(conn,connI,cell1,cell2);
1540 return AreCellsEqual7(conn,connI,cell1,cell2);
1542 throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1546 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1548 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1550 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1551 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1556 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1558 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1560 int sz=connI[cell1+1]-connI[cell1];
1561 if(sz==connI[cell2+1]-connI[cell2])
1563 if(conn[connI[cell1]]==conn[connI[cell2]])
1565 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1566 unsigned dim=cm.getDimension();
1572 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1573 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1574 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1575 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1576 return work!=tmp+sz1?1:0;
1579 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1582 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1589 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1591 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1593 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1595 if(conn[connI[cell1]]==conn[connI[cell2]])
1597 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1598 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1606 * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1608 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1610 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1612 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1613 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1620 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1622 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1624 int sz=connI[cell1+1]-connI[cell1];
1625 if(sz==connI[cell2+1]-connI[cell2])
1627 if(conn[connI[cell1]]==conn[connI[cell2]])
1629 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1630 unsigned dim=cm.getDimension();
1636 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1637 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1638 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1639 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1644 std::reverse_iterator<int *> it1((int *)tmp+sz1);
1645 std::reverse_iterator<int *> it2((int *)tmp);
1646 if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1652 return work!=tmp+sz1?1:0;
1655 {//case of SEG2 and SEG3
1656 if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1658 if(!cm.isQuadratic())
1660 std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1661 std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1662 if(std::equal(it1,it2,conn+connI[cell2]+1))
1668 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])
1675 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1682 * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1683 * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1684 * and result remains unchanged.
1685 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1686 * If in 'candidates' pool -1 value is considered as an empty value.
1687 * WARNING this method returns only ONE set of result !
1689 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1691 if(candidates.size()<1)
1694 std::vector<int>::const_iterator iter=candidates.begin();
1695 int start=(*iter++);
1696 for(;iter!=candidates.end();iter++)
1698 int status=AreCellsEqual(conn,connI,start,*iter,compType);
1703 result->pushBackSilent(start);
1707 result->pushBackSilent(*iter);
1709 result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1716 * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1717 * This method keeps the coordiantes of \a this. This method is time consuming and is called
1719 * \param [in] compType input specifying the technique used to compare cells each other.
1720 * - 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.
1721 * - 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)
1722 * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1723 * - 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
1724 * can be used for users not sensitive to orientation of cell
1725 * \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.
1726 * \param [out] commonCells
1727 * \param [out] commonCellsI
1728 * \return the correspondance array old to new in a newly allocated array.
1731 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1733 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1734 getReverseNodalConnectivity(revNodal,revNodalI);
1735 FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1738 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1739 DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) throw(INTERP_KERNEL::Exception)
1741 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1742 int nbOfCells=nodalI->getNumberOfTuples()-1;
1743 commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1744 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1745 const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1746 std::vector<bool> isFetched(nbOfCells,false);
1749 for(int i=0;i<nbOfCells;i++)
1753 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1754 std::vector<int> v,v2;
1755 if(connOfNode!=connPtr+connIPtr[i+1])
1757 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1758 v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1761 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1765 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1766 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1767 v2.resize(std::distance(v2.begin(),it));
1771 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1773 int pos=commonCellsI->back();
1774 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1775 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1776 isFetched[*it]=true;
1784 for(int i=startCellId;i<nbOfCells;i++)
1788 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1789 std::vector<int> v,v2;
1790 if(connOfNode!=connPtr+connIPtr[i+1])
1792 v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1795 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1799 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1800 v2.resize(std::distance(v2.begin(),it));
1804 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1806 int pos=commonCellsI->back();
1807 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1808 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1809 isFetched[*it]=true;
1815 commonCellsArr=commonCells.retn();
1816 commonCellsIArr=commonCellsI.retn();
1820 * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1821 * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1822 * than \a other->getNumberOfCells() in the returned array means that there is no
1823 * corresponding cell in \a this mesh.
1824 * It is expected that \a this and \a other meshes share the same node coordinates
1825 * array, if it is not so an exception is thrown.
1826 * \param [in] other - the mesh to compare with.
1827 * \param [in] compType - specifies a cell comparison technique. For meaning of its
1828 * valid values [0,1,2], see zipConnectivityTraducer().
1829 * \param [out] arr - a new instance of DataArrayInt returning correspondence
1830 * between cells of the two meshes. It contains \a other->getNumberOfCells()
1831 * values. The caller is to delete this array using
1832 * decrRef() as it is no more needed.
1833 * \return bool - \c true if all cells of \a other mesh are present in the \a this
1836 * \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1837 * \ref py_mcumesh_areCellsIncludedIn "Here is a Python example".
1838 * \sa checkDeepEquivalOnSameNodesWith()
1839 * \sa checkGeoEquivalWith()
1841 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1843 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1844 int nbOfCells=getNumberOfCells();
1845 static const int possibleCompType[]={0,1,2};
1846 if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1848 std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1849 std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1851 throw INTERP_KERNEL::Exception(oss.str().c_str());
1853 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1854 arr=o2n->substr(nbOfCells);
1855 arr->setName(other->getName());
1857 if(other->getNumberOfCells()==0)
1859 return arr->getMaxValue(tmp)<nbOfCells;
1863 * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1864 * This method tries to determine if \b other is fully included in \b this.
1865 * The main difference is that this method is not expected to throw exception.
1866 * This method has two outputs :
1868 * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1869 * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1871 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1873 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1874 DataArrayInt *commonCells=0,*commonCellsI=0;
1875 int thisNbCells=getNumberOfCells();
1876 mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1877 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1878 const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1879 int otherNbCells=other->getNumberOfCells();
1880 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1881 arr2->alloc(otherNbCells,1);
1882 arr2->fillWithZero();
1883 int *arr2Ptr=arr2->getPointer();
1884 int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1885 for(int i=0;i<nbOfCommon;i++)
1887 int start=commonCellsPtr[commonCellsIPtr[i]];
1888 if(start<thisNbCells)
1890 for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1892 int sig=commonCellsPtr[j]>0?1:-1;
1893 int val=std::abs(commonCellsPtr[j])-1;
1894 if(val>=thisNbCells)
1895 arr2Ptr[val-thisNbCells]=sig*(start+1);
1899 arr2->setName(other->getName());
1900 if(arr2->presenceOfValue(0))
1906 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1909 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1910 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1912 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1913 std::vector<const MEDCouplingUMesh *> ms(2);
1916 return MergeUMeshesOnSameCoords(ms);
1920 * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1921 * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1922 * cellIds is not given explicitely but by a range python like.
1924 * \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.
1925 * \return a newly allocated
1927 * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1928 * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1930 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const
1932 if(getMeshDimension()!=-1)
1933 return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
1936 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
1938 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1940 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1942 return const_cast<MEDCouplingUMesh *>(this);
1947 * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
1948 * The result mesh shares or not the node coordinates array with \a this mesh depending
1949 * on \a keepCoords parameter.
1950 * \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
1951 * to write this mesh to the MED file, its cells must be sorted using
1952 * sortCellsInMEDFileFrmt().
1953 * \param [in] begin - an array of cell ids to include to the new mesh.
1954 * \param [in] end - a pointer to last-plus-one-th element of \a begin.
1955 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
1956 * array of \a this mesh, else "free" nodes are removed from the result mesh
1957 * by calling zipCoords().
1958 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
1959 * to delete this mesh using decrRef() as it is no more needed.
1960 * \throw If the coordinates array is not set.
1961 * \throw If the nodal connectivity of cells is not defined.
1962 * \throw If any cell id in the array \a begin is not valid.
1964 * \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
1965 * \ref py_mcumesh_buildPartOfMySelf "Here is a Python example".
1967 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
1969 if(getMeshDimension()!=-1)
1970 return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
1974 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1976 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1978 return const_cast<MEDCouplingUMesh *>(this);
1983 * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
1985 * 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.
1986 * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
1987 * The number of cells of \b this will remain the same with this method.
1989 * \param [in] begin begin of cell ids (included) of cells in this to assign
1990 * \param [in] end end of cell ids (excluded) of cells in this to assign
1991 * \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 ).
1992 * Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
1994 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
1996 checkConnectivityFullyDefined();
1997 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1998 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1999 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2000 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2002 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2003 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2004 throw INTERP_KERNEL::Exception(oss.str().c_str());
2006 int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2007 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2009 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2010 throw INTERP_KERNEL::Exception(oss.str().c_str());
2012 int nbOfCells=getNumberOfCells();
2013 bool easyAssign=true;
2014 const int *connI=_nodal_connec_index->getConstPointer();
2015 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2016 for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2018 if(*it>=0 && *it<nbOfCells)
2020 easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2024 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2025 throw INTERP_KERNEL::Exception(oss.str().c_str());
2030 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2035 DataArrayInt *arrOut=0,*arrIOut=0;
2036 MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2038 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2039 setConnectivity(arrOut,arrIOut,true);
2043 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2045 checkConnectivityFullyDefined();
2046 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2047 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2048 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2049 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2051 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2052 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2053 throw INTERP_KERNEL::Exception(oss.str().c_str());
2055 int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2056 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2058 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2059 throw INTERP_KERNEL::Exception(oss.str().c_str());
2061 int nbOfCells=getNumberOfCells();
2062 bool easyAssign=true;
2063 const int *connI=_nodal_connec_index->getConstPointer();
2064 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2066 for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2068 if(it>=0 && it<nbOfCells)
2070 easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2074 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2075 throw INTERP_KERNEL::Exception(oss.str().c_str());
2080 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2085 DataArrayInt *arrOut=0,*arrIOut=0;
2086 MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2088 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2089 setConnectivity(arrOut,arrIOut,true);
2094 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2095 * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2096 * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2097 * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2099 * \param [in] begin input start of array of node ids.
2100 * \param [in] end input end of array of node ids.
2101 * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2102 * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2104 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2106 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2107 checkConnectivityFullyDefined();
2109 int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2110 std::vector<bool> fastFinder(sz,false);
2111 for(const int *work=begin;work!=end;work++)
2112 if(*work>=0 && *work<sz)
2113 fastFinder[*work]=true;
2114 int nbOfCells=getNumberOfCells();
2115 const int *conn=getNodalConnectivity()->getConstPointer();
2116 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2117 for(int i=0;i<nbOfCells;i++)
2119 int ref=0,nbOfHit=0;
2120 for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2124 if(fastFinder[*work2])
2127 if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2128 cellIdsKept->pushBackSilent(i);
2130 cellIdsKeptArr=cellIdsKept.retn();
2134 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2135 * this->getMeshDimension(), that bound some cells of \a this mesh.
2136 * The cells of lower dimension to include to the result mesh are selected basing on
2137 * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2138 * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2139 * ==\c false, a cell is copied if any its node is in the array of node ids. The
2140 * created mesh shares the node coordinates array with \a this mesh.
2141 * \param [in] begin - the array of node ids.
2142 * \param [in] end - a pointer to the (last+1)-th element of \a begin.
2143 * \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2144 * array \a begin are added, else cells whose any node is in the
2145 * array \a begin are added.
2146 * \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2147 * to delete this mesh using decrRef() as it is no more needed.
2148 * \throw If the coordinates array is not set.
2149 * \throw If the nodal connectivity of cells is not defined.
2150 * \throw If any node id in \a begin is not valid.
2152 * \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2153 * \ref py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2155 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2157 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2158 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2159 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2160 desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2161 return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2165 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2166 * this->getMeshDimension(), which bound only one cell of \a this mesh.
2167 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2168 * array of \a this mesh, else "free" nodes are removed from the result mesh
2169 * by calling zipCoords().
2170 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2171 * to delete this mesh using decrRef() as it is no more needed.
2172 * \throw If the coordinates array is not set.
2173 * \throw If the nodal connectivity of cells is not defined.
2175 * \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2176 * \ref py_mcumesh_buildBoundaryMesh "Here is a Python example".
2178 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2180 DataArrayInt *desc=DataArrayInt::New();
2181 DataArrayInt *descIndx=DataArrayInt::New();
2182 DataArrayInt *revDesc=DataArrayInt::New();
2183 DataArrayInt *revDescIndx=DataArrayInt::New();
2185 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2188 descIndx->decrRef();
2189 int nbOfCells=meshDM1->getNumberOfCells();
2190 const int *revDescIndxC=revDescIndx->getConstPointer();
2191 std::vector<int> boundaryCells;
2192 for(int i=0;i<nbOfCells;i++)
2193 if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2194 boundaryCells.push_back(i);
2195 revDescIndx->decrRef();
2196 MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2201 * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2202 * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2203 * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown.
2205 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2207 checkFullyDefined();
2208 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2209 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2210 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2211 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2213 buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2214 desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2216 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2217 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2218 const int *revDescPtr=revDesc->getConstPointer();
2219 const int *revDescIndxPtr=revDescIndx->getConstPointer();
2220 int nbOfCells=getNumberOfCells();
2221 std::vector<bool> ret1(nbOfCells,false);
2223 for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2224 if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2225 { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2227 DataArrayInt *ret2=DataArrayInt::New();
2229 int *ret2Ptr=ret2->getPointer();
2231 for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2234 ret2->setName("BoundaryCells");
2239 * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2240 * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2241 * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2242 * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2244 * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2245 * This method method returns cells ids set s = s1 + s2 where :
2247 * - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2248 * - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2250 * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2251 * are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2253 * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2254 * \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
2255 * cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2257 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2259 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2260 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2261 checkConnectivityFullyDefined();
2262 otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2263 if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2264 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2265 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2266 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2267 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2268 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2269 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2270 const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2271 DataArrayInt *idsOtherInConsti=0;
2272 bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2273 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2275 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2277 for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2278 s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2279 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2280 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2281 DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2282 ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2283 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2284 ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2285 neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2286 RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2287 neighThisPartAuto=0;
2288 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2289 const int li[2]={0,1};
2290 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2291 s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2292 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2295 cellIdsRk0=s0arr.retn();
2296 cellIdsRk1=s_renum1.retn();
2300 * 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
2301 * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2303 * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2305 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2307 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2308 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2309 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2310 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2312 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2313 revDesc=0; desc=0; descIndx=0;
2314 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2315 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2316 return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2320 * Finds nodes lying on the boundary of \a this mesh.
2321 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2322 * nodes. The caller is to delete this array using decrRef() as it is no
2324 * \throw If the coordinates array is not set.
2325 * \throw If the nodal connectivity of cells is node defined.
2327 * \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2328 * \ref py_mcumesh_findBoundaryNodes "Here is a Python example".
2330 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2332 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2333 return skin->computeFetchedNodeIds();
2336 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2339 return const_cast<MEDCouplingUMesh *>(this);
2343 * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2344 * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2345 * 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.
2346 * 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.
2347 * 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.
2349 * \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
2350 * parameter is altered during the call.
2351 * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2352 * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2353 * \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.
2355 * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2357 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2358 DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const throw(INTERP_KERNEL::Exception)
2360 checkFullyDefined();
2361 otherDimM1OnSameCoords.checkFullyDefined();
2362 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2363 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2364 if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2365 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2366 DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2367 findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2368 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2369 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2370 s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2371 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2372 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2373 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2374 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2375 cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2377 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2378 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2379 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2380 DataArrayInt *idsTmp=0;
2381 bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2382 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2384 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2385 MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2386 DataArrayInt *tmp0=0,*tmp1=0;
2387 ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2388 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2389 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2390 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2391 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2392 cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2393 cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2395 cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2396 cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2397 nodeIdsToDuplicate=s3.retn();
2401 * This method operates a modification of the connectivity and coords in \b this.
2402 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2403 * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2404 * 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
2405 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2406 * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2408 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2410 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2411 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2413 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2415 int nbOfNodes=getNumberOfNodes();
2416 duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2417 duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2421 * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2422 * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2423 * This method is a generalization of shiftNodeNumbersInConn().
2424 * \warning This method performs no check of validity of new ids. **Use it with care !**
2425 * \param [in] newNodeNumbersO2N - a permutation array, of length \a
2426 * this->getNumberOfNodes(), in "Old to New" mode.
2427 * See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2428 * \throw If the nodal connectivity of cells is not defined.
2430 * \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2431 * \ref py_mcumesh_renumberNodesInConn "Here is a Python example".
2433 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2435 checkConnectivityFullyDefined();
2436 int *conn=getNodalConnectivity()->getPointer();
2437 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2438 int nbOfCells=getNumberOfCells();
2439 for(int i=0;i<nbOfCells;i++)
2440 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2442 int& node=conn[iconn];
2443 if(node>=0)//avoid polyhedron separator
2445 node=newNodeNumbersO2N[node];
2448 _nodal_connec->declareAsNew();
2453 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2454 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2455 * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2457 * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2459 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2461 checkConnectivityFullyDefined();
2462 int *conn=getNodalConnectivity()->getPointer();
2463 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2464 int nbOfCells=getNumberOfCells();
2465 for(int i=0;i<nbOfCells;i++)
2466 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2468 int& node=conn[iconn];
2469 if(node>=0)//avoid polyhedron separator
2474 _nodal_connec->declareAsNew();
2479 * This method operates a modification of the connectivity in \b this.
2480 * 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.
2481 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2482 * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2483 * 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
2484 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2485 * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2487 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2488 * As an another consequense after the call of this method \b this can be transiently non cohrent.
2490 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2491 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2492 * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ).
2494 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2496 checkConnectivityFullyDefined();
2497 std::map<int,int> m;
2499 for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2501 int *conn=getNodalConnectivity()->getPointer();
2502 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2503 int nbOfCells=getNumberOfCells();
2504 for(int i=0;i<nbOfCells;i++)
2505 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2507 int& node=conn[iconn];
2508 if(node>=0)//avoid polyhedron separator
2510 std::map<int,int>::iterator it=m.find(node);
2519 * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2521 * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2522 * After the call of this method the number of cells remains the same as before.
2524 * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2525 * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2526 * be strictly in [0;this->getNumberOfCells()).
2528 * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2529 * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2530 * should be contained in[0;this->getNumberOfCells()).
2532 * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2534 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2536 checkConnectivityFullyDefined();
2537 int nbCells=getNumberOfCells();
2538 const int *array=old2NewBg;
2540 array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2542 const int *conn=_nodal_connec->getConstPointer();
2543 const int *connI=_nodal_connec_index->getConstPointer();
2544 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2545 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2546 const int *n2oPtr=n2o->begin();
2547 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2548 newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2549 newConn->copyStringInfoFrom(*_nodal_connec);
2550 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2551 newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2552 newConnI->copyStringInfoFrom(*_nodal_connec_index);
2554 int *newC=newConn->getPointer();
2555 int *newCI=newConnI->getPointer();
2558 for(int i=0;i<nbCells;i++)
2561 int nbOfElts=connI[pos+1]-connI[pos];
2562 newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2567 setConnectivity(newConn,newConnI);
2569 free(const_cast<int *>(array));
2573 * Finds cells whose bounding boxes intersect a given bounding box.
2574 * \param [in] bbox - an array defining the bounding box via coordinates of its
2575 * extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2577 * \param [in] eps - a factor used to increase size of the bounding box of cell
2578 * before comparing it with \a bbox. This factor is multiplied by the maximal
2579 * extent of the bounding box of cell to produce an addition to this bounding box.
2580 * \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2581 * cells. The caller is to delete this array using decrRef() as it is no more
2583 * \throw If the coordinates array is not set.
2584 * \throw If the nodal connectivity of cells is not defined.
2586 * \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2587 * \ref py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2589 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2591 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2592 if(getMeshDimension()==-1)
2594 elems->pushBackSilent(0);
2595 return elems.retn();
2597 int dim=getSpaceDimension();
2598 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2599 const int* conn = getNodalConnectivity()->getConstPointer();
2600 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2601 const double* coords = getCoords()->getConstPointer();
2602 int nbOfCells=getNumberOfCells();
2603 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2605 for (int i=0; i<dim; i++)
2607 elem_bb[i*2]=std::numeric_limits<double>::max();
2608 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2611 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2613 int node= conn[inode];
2614 if(node>=0)//avoid polyhedron separator
2616 for (int idim=0; idim<dim; idim++)
2618 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2620 elem_bb[idim*2] = coords[node*dim+idim] ;
2622 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2624 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2629 if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2630 elems->pushBackSilent(ielem);
2632 return elems.retn();
2636 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2637 * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2638 * added in 'elems' parameter.
2640 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2642 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2643 if(getMeshDimension()==-1)
2645 elems->pushBackSilent(0);
2646 return elems.retn();
2648 int dim=getSpaceDimension();
2649 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2650 const int* conn = getNodalConnectivity()->getConstPointer();
2651 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2652 const double* coords = getCoords()->getConstPointer();
2653 int nbOfCells=getNumberOfCells();
2654 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2656 for (int i=0; i<dim; i++)
2658 elem_bb[i*2]=std::numeric_limits<double>::max();
2659 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2662 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2664 int node= conn[inode];
2665 if(node>=0)//avoid polyhedron separator
2667 for (int idim=0; idim<dim; idim++)
2669 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2671 elem_bb[idim*2] = coords[node*dim+idim] ;
2673 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2675 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2680 if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2681 elems->pushBackSilent(ielem);
2683 return elems.retn();
2687 * Returns a type of a cell by its id.
2688 * \param [in] cellId - the id of the cell of interest.
2689 * \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2690 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2692 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2694 const int *ptI=_nodal_connec_index->getConstPointer();
2695 const int *pt=_nodal_connec->getConstPointer();
2696 if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2697 return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2700 std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2701 throw INTERP_KERNEL::Exception(oss.str().c_str());
2706 * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2707 * This method does not throw exception if geometric type \a type is not in \a this.
2708 * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2709 * The coordinates array is not considered here.
2711 * \param [in] type the geometric type
2712 * \return cell ids in this having geometric type \a type.
2714 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2717 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2719 checkConnectivityFullyDefined();
2720 int nbCells=getNumberOfCells();
2721 int mdim=getMeshDimension();
2722 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2723 if(mdim!=(int)cm.getDimension())
2724 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2725 const int *ptI=_nodal_connec_index->getConstPointer();
2726 const int *pt=_nodal_connec->getConstPointer();
2727 for(int i=0;i<nbCells;i++)
2729 if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2730 ret->pushBackSilent(i);
2736 * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2738 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2740 const int *ptI=_nodal_connec_index->getConstPointer();
2741 const int *pt=_nodal_connec->getConstPointer();
2742 int nbOfCells=getNumberOfCells();
2744 for(int i=0;i<nbOfCells;i++)
2745 if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2751 * Returns the nodal connectivity of a given cell.
2752 * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2753 * all returned node ids can be used in getCoordinatesOfNode().
2754 * \param [in] cellId - an id of the cell of interest.
2755 * \param [in,out] conn - a vector where the node ids are appended. It is not
2756 * cleared before the appending.
2757 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2759 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2761 const int *ptI=_nodal_connec_index->getConstPointer();
2762 const int *pt=_nodal_connec->getConstPointer();
2763 for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2768 std::string MEDCouplingUMesh::simpleRepr() const
2770 static const char msg0[]="No coordinates specified !";
2771 std::ostringstream ret;
2772 ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2773 ret << "Description of mesh : \"" << getDescription() << "\"\n";
2775 double tt=getTime(tmpp1,tmpp2);
2776 ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2777 ret << "Iteration : " << tmpp1 << " Order : " << tmpp2 << "\n";
2779 { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2781 { ret << " Mesh dimension has not been set or is invalid !"; }
2784 const int spaceDim=getSpaceDimension();
2785 ret << spaceDim << "\nInfo attached on space dimension : ";
2786 for(int i=0;i<spaceDim;i++)
2787 ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2791 ret << msg0 << "\n";
2792 ret << "Number of nodes : ";
2794 ret << getNumberOfNodes() << "\n";
2796 ret << msg0 << "\n";
2797 ret << "Number of cells : ";
2798 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2799 ret << getNumberOfCells() << "\n";
2801 ret << "No connectivity specified !" << "\n";
2802 ret << "Cell types present : ";
2803 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2805 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2806 ret << cm.getRepr() << " ";
2812 std::string MEDCouplingUMesh::advancedRepr() const
2814 std::ostringstream ret;
2815 ret << simpleRepr();
2816 ret << "\nCoordinates array : \n___________________\n\n";
2818 _coords->reprWithoutNameStream(ret);
2820 ret << "No array set !\n";
2821 ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2822 reprConnectivityOfThisLL(ret);
2827 * This method returns a C++ code that is a dump of \a this.
2828 * This method will throw if this is not fully defined.
2830 std::string MEDCouplingUMesh::cppRepr() const
2832 static const char coordsName[]="coords";
2833 static const char connName[]="conn";
2834 static const char connIName[]="connI";
2835 checkFullyDefined();
2836 std::ostringstream ret; ret << "// coordinates" << std::endl;
2837 _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2838 _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2839 _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2840 ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2841 ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2842 ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2843 ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2847 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2849 std::ostringstream ret;
2850 reprConnectivityOfThisLL(ret);
2855 * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
2856 * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2857 * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2860 * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2861 * 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
2862 * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2864 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
2866 int mdim=getMeshDimension();
2868 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2869 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
2870 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
2871 bool needToCpyCT=true;
2874 tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2882 if(!_nodal_connec_index)
2884 tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2889 tmp2=_nodal_connec_index;
2892 ret->setConnectivity(tmp1,tmp2,false);
2897 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2898 ret->setCoords(coords);
2901 ret->setCoords(_coords);
2905 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
2907 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2909 int nbOfCells=getNumberOfCells();
2910 const int *c=_nodal_connec->getConstPointer();
2911 const int *ci=_nodal_connec_index->getConstPointer();
2912 for(int i=0;i<nbOfCells;i++)
2914 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
2915 stream << "Cell #" << i << " " << cm.getRepr() << " : ";
2916 std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
2921 stream << "Connectivity not defined !\n";
2924 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
2926 const int *ptI=_nodal_connec_index->getConstPointer();
2927 const int *pt=_nodal_connec->getConstPointer();
2928 if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
2929 return ptI[cellId+1]-ptI[cellId]-1;
2931 return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
2935 * Returns types of cells of the specified part of \a this mesh.
2936 * This method avoids computing sub-mesh explicitely to get its types.
2937 * \param [in] begin - an array of cell ids of interest.
2938 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
2939 * \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
2940 * describing the cell types.
2941 * \throw If the coordinates array is not set.
2942 * \throw If the nodal connectivity of cells is not defined.
2943 * \sa getAllGeoTypes()
2945 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
2947 checkFullyDefined();
2948 std::set<INTERP_KERNEL::NormalizedCellType> ret;
2949 const int *conn=_nodal_connec->getConstPointer();
2950 const int *connIndex=_nodal_connec_index->getConstPointer();
2951 for(const int *w=begin;w!=end;w++)
2952 ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
2957 * Defines the nodal connectivity using given connectivity arrays. Optionally updates
2958 * a set of types of cells constituting \a this mesh.
2959 * This method is for advanced users having prepared their connectivity before. For
2960 * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
2961 * \param [in] conn - the nodal connectivity array.
2962 * \param [in] connIndex - the nodal connectivity index array.
2963 * \param [in] isComputingTypes - if \c true, the set of types constituting \a this
2966 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
2968 DataArrayInt::SetArrayIn(conn,_nodal_connec);
2969 DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
2970 if(isComputingTypes)
2976 * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
2977 * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
2979 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
2980 _nodal_connec(0),_nodal_connec_index(0),
2981 _types(other._types)
2983 if(other._nodal_connec)
2984 _nodal_connec=other._nodal_connec->performCpy(deepCopy);
2985 if(other._nodal_connec_index)
2986 _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
2989 MEDCouplingUMesh::~MEDCouplingUMesh()
2992 _nodal_connec->decrRef();
2993 if(_nodal_connec_index)
2994 _nodal_connec_index->decrRef();
2998 * Recomputes a set of cell types of \a this mesh. For more info see
2999 * \ref MEDCouplingUMeshNodalConnectivity.
3001 void MEDCouplingUMesh::computeTypes()
3003 if(_nodal_connec && _nodal_connec_index)
3006 const int *conn=_nodal_connec->getConstPointer();
3007 const int *connIndex=_nodal_connec_index->getConstPointer();
3008 int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
3010 for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
3011 _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
3016 * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3018 void MEDCouplingUMesh::checkFullyDefined() const
3020 if(!_nodal_connec_index || !_nodal_connec || !_coords)
3021 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3025 * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3027 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3029 if(!_nodal_connec_index || !_nodal_connec)
3030 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3034 * Returns a number of cells constituting \a this mesh.
3035 * \return int - the number of cells in \a this mesh.
3036 * \throw If the nodal connectivity of cells is not defined.
3038 int MEDCouplingUMesh::getNumberOfCells() const
3040 if(_nodal_connec_index)
3041 return _nodal_connec_index->getNumberOfTuples()-1;
3046 throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3050 * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3051 * mesh. For more info see \ref MEDCouplingMeshesPage.
3052 * \return int - the dimension of \a this mesh.
3053 * \throw If the mesh dimension is not defined using setMeshDimension().
3055 int MEDCouplingUMesh::getMeshDimension() const
3058 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3063 * Returns a length of the nodal connectivity array.
3064 * This method is for test reason. Normally the integer returned is not useable by
3065 * user. For more info see \ref MEDCouplingUMeshNodalConnectivity.
3066 * \return int - the length of the nodal connectivity array.
3068 int MEDCouplingUMesh::getMeshLength() const
3070 return _nodal_connec->getNbOfElems();
3074 * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3076 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3078 MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3079 tinyInfo.push_back(getMeshDimension());
3080 tinyInfo.push_back(getNumberOfCells());
3082 tinyInfo.push_back(getMeshLength());
3084 tinyInfo.push_back(-1);
3088 * First step of unserialization process.
3090 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3092 return tinyInfo[6]<=0;
3096 * Second step of serialization process.
3097 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3099 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3101 MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3103 a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3107 * Third and final step of serialization process.
3109 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3111 MEDCouplingPointSet::serialize(a1,a2);
3112 if(getMeshDimension()>-1)
3114 a1=DataArrayInt::New();
3115 a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3116 int *ptA1=a1->getPointer();
3117 const int *conn=getNodalConnectivity()->getConstPointer();
3118 const int *index=getNodalConnectivityIndex()->getConstPointer();
3119 ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3120 std::copy(conn,conn+getMeshLength(),ptA1);
3127 * Second and final unserialization process.
3128 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3130 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3132 MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3133 setMeshDimension(tinyInfo[5]);
3137 const int *recvBuffer=a1->getConstPointer();
3138 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3139 myConnecIndex->alloc(tinyInfo[6]+1,1);
3140 std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3141 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3142 myConnec->alloc(tinyInfo[7],1);
3143 std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3144 setConnectivity(myConnec, myConnecIndex);
3149 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3150 * CellIds are given using range specified by a start an end and step.
3152 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3154 checkFullyDefined();
3155 int ncell=getNumberOfCells();
3156 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3157 ret->_mesh_dim=_mesh_dim;
3158 ret->setCoords(_coords);
3159 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3160 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3161 int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3163 const int *conn=_nodal_connec->getConstPointer();
3164 const int *connIndex=_nodal_connec_index->getConstPointer();
3165 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3167 if(work>=0 && work<ncell)
3169 newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3173 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3174 throw INTERP_KERNEL::Exception(oss.str().c_str());
3177 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3178 int *newConnPtr=newConn->getPointer();
3179 std::set<INTERP_KERNEL::NormalizedCellType> types;
3181 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3183 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3184 newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3186 ret->setConnectivity(newConn,newConnI,false);
3188 ret->copyTinyInfoFrom(this);
3193 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3194 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3195 * The return newly allocated mesh will share the same coordinates as \a this.
3197 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3199 checkConnectivityFullyDefined();
3200 int ncell=getNumberOfCells();
3201 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3202 ret->_mesh_dim=_mesh_dim;
3203 ret->setCoords(_coords);
3204 std::size_t nbOfElemsRet=std::distance(begin,end);
3205 int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3207 const int *conn=_nodal_connec->getConstPointer();
3208 const int *connIndex=_nodal_connec_index->getConstPointer();
3210 for(const int *work=begin;work!=end;work++,newNbring++)
3212 if(*work>=0 && *work<ncell)
3213 connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3217 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3218 throw INTERP_KERNEL::Exception(oss.str().c_str());
3221 int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3222 int *connRetWork=connRet;
3223 std::set<INTERP_KERNEL::NormalizedCellType> types;
3224 for(const int *work=begin;work!=end;work++)
3226 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3227 connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3229 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3230 connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3231 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3232 connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3233 ret->setConnectivity(connRetArr,connIndexRetArr,false);
3235 ret->copyTinyInfoFrom(this);
3240 * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3242 * For 1D cells, the returned field contains lengths.<br>
3243 * For 2D cells, the returned field contains areas.<br>
3244 * For 3D cells, the returned field contains volumes.
3245 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3246 * orientation, i.e. the volume is always positive.
3247 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3248 * and one time . The caller is to delete this field using decrRef() as it is no
3251 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3253 std::string name="MeasureOfMesh_";
3255 int nbelem=getNumberOfCells();
3256 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3257 field->setName(name);
3258 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3259 array->alloc(nbelem,1);
3260 double *area_vol=array->getPointer();
3261 field->setArray(array) ; array=0;
3262 field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3263 field->synchronizeTimeWithMesh();
3264 if(getMeshDimension()!=-1)
3267 INTERP_KERNEL::NormalizedCellType type;
3268 int dim_space=getSpaceDimension();
3269 const double *coords=getCoords()->getConstPointer();
3270 const int *connec=getNodalConnectivity()->getConstPointer();
3271 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3272 for(int iel=0;iel<nbelem;iel++)
3274 ipt=connec_index[iel];
3275 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3276 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);
3279 std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3283 area_vol[0]=std::numeric_limits<double>::max();
3285 return field.retn();
3289 * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3291 * For 1D cells, the returned array contains lengths.<br>
3292 * For 2D cells, the returned array contains areas.<br>
3293 * For 3D cells, the returned array contains volumes.
3294 * This method avoids building explicitly a part of \a this mesh to perform the work.
3295 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3296 * orientation, i.e. the volume is always positive.
3297 * \param [in] begin - an array of cell ids of interest.
3298 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3299 * \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3300 * delete this array using decrRef() as it is no more needed.
3302 * \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3303 * \ref py_mcumesh_getPartMeasureField "Here is a Python example".
3304 * \sa getMeasureField()
3306 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3308 std::string name="PartMeasureOfMesh_";
3310 int nbelem=(int)std::distance(begin,end);
3311 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3312 array->setName(name);
3313 array->alloc(nbelem,1);
3314 double *area_vol=array->getPointer();
3315 if(getMeshDimension()!=-1)
3318 INTERP_KERNEL::NormalizedCellType type;
3319 int dim_space=getSpaceDimension();
3320 const double *coords=getCoords()->getConstPointer();
3321 const int *connec=getNodalConnectivity()->getConstPointer();
3322 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3323 for(const int *iel=begin;iel!=end;iel++)
3325 ipt=connec_index[*iel];
3326 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3327 *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3330 std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3334 area_vol[0]=std::numeric_limits<double>::max();
3336 return array.retn();
3340 * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3341 * \a this one. The returned field contains the dual cell volume for each corresponding
3342 * node in \a this mesh. In other words, the field returns the getMeasureField() of
3343 * the dual mesh in P1 sens of \a this.<br>
3344 * For 1D cells, the returned field contains lengths.<br>
3345 * For 2D cells, the returned field contains areas.<br>
3346 * For 3D cells, the returned field contains volumes.
3347 * This method is useful to check "P1*" conservative interpolators.
3348 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3349 * orientation, i.e. the volume is always positive.
3350 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3351 * nodes and one time. The caller is to delete this array using decrRef() as
3352 * it is no more needed.
3354 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3356 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3357 std::string name="MeasureOnNodeOfMesh_";
3359 int nbNodes=getNumberOfNodes();
3360 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3361 double cst=1./((double)getMeshDimension()+1.);
3362 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3363 array->alloc(nbNodes,1);
3364 double *valsToFill=array->getPointer();
3365 std::fill(valsToFill,valsToFill+nbNodes,0.);
3366 const double *values=tmp->getArray()->getConstPointer();
3367 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3368 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3369 getReverseNodalConnectivity(da,daInd);
3370 const int *daPtr=da->getConstPointer();
3371 const int *daIPtr=daInd->getConstPointer();
3372 for(int i=0;i<nbNodes;i++)
3373 for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3374 valsToFill[i]+=cst*values[*cell];
3376 ret->setArray(array);
3381 * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3382 * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3383 * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3384 * and are normalized.
3385 * <br> \a this can be either
3386 * - a 2D mesh in 2D or 3D space or
3387 * - an 1D mesh in 2D space.
3389 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3390 * cells and one time. The caller is to delete this field using decrRef() as
3391 * it is no more needed.
3392 * \throw If the nodal connectivity of cells is not defined.
3393 * \throw If the coordinates array is not set.
3394 * \throw If the mesh dimension is not set.
3395 * \throw If the mesh and space dimension is not as specified above.
3397 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3399 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3400 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3401 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3402 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3403 int nbOfCells=getNumberOfCells();
3404 int nbComp=getMeshDimension()+1;
3405 array->alloc(nbOfCells,nbComp);
3406 double *vals=array->getPointer();
3407 const int *connI=_nodal_connec_index->getConstPointer();
3408 const int *conn=_nodal_connec->getConstPointer();
3409 const double *coords=_coords->getConstPointer();
3410 if(getMeshDimension()==2)
3412 if(getSpaceDimension()==3)
3414 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3415 const double *locPtr=loc->getConstPointer();
3416 for(int i=0;i<nbOfCells;i++,vals+=3)
3418 int offset=connI[i];
3419 INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3420 double n=INTERP_KERNEL::norm<3>(vals);
3421 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3426 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3427 const double *isAbsPtr=isAbs->getArray()->begin();
3428 for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3429 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3432 else//meshdimension==1
3435 for(int i=0;i<nbOfCells;i++)
3437 int offset=connI[i];
3438 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3439 double n=INTERP_KERNEL::norm<2>(tmp);
3440 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3445 ret->setArray(array);
3447 ret->synchronizeTimeWithSupport();
3452 * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3453 * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3454 * and are normalized.
3455 * <br> \a this can be either
3456 * - a 2D mesh in 2D or 3D space or
3457 * - an 1D mesh in 2D space.
3459 * This method avoids building explicitly a part of \a this mesh to perform the work.
3460 * \param [in] begin - an array of cell ids of interest.
3461 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3462 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3463 * cells and one time. The caller is to delete this field using decrRef() as
3464 * it is no more needed.
3465 * \throw If the nodal connectivity of cells is not defined.
3466 * \throw If the coordinates array is not set.
3467 * \throw If the mesh dimension is not set.
3468 * \throw If the mesh and space dimension is not as specified above.
3469 * \sa buildOrthogonalField()
3471 * \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3472 * \ref py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3474 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3476 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3477 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3478 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3479 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3480 std::size_t nbelems=std::distance(begin,end);
3481 int nbComp=getMeshDimension()+1;
3482 array->alloc((int)nbelems,nbComp);
3483 double *vals=array->getPointer();
3484 const int *connI=_nodal_connec_index->getConstPointer();
3485 const int *conn=_nodal_connec->getConstPointer();
3486 const double *coords=_coords->getConstPointer();
3487 if(getMeshDimension()==2)
3489 if(getSpaceDimension()==3)
3491 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3492 const double *locPtr=loc->getConstPointer();
3493 for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3495 int offset=connI[*i];
3496 INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3497 double n=INTERP_KERNEL::norm<3>(vals);
3498 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3503 for(std::size_t i=0;i<nbelems;i++)
3504 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3507 else//meshdimension==1
3510 for(const int *i=begin;i!=end;i++)
3512 int offset=connI[*i];
3513 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3514 double n=INTERP_KERNEL::norm<2>(tmp);
3515 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3520 ret->setArray(array);
3522 ret->synchronizeTimeWithSupport();
3527 * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3528 * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3529 * and are \b not normalized.
3530 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3531 * cells and one time. The caller is to delete this field using decrRef() as
3532 * it is no more needed.
3533 * \throw If the nodal connectivity of cells is not defined.
3534 * \throw If the coordinates array is not set.
3535 * \throw If \a this->getMeshDimension() != 1.
3536 * \throw If \a this mesh includes cells of type other than SEG2.
3538 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3540 if(getMeshDimension()!=1)
3541 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3542 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3543 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3544 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3545 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3546 int nbOfCells=getNumberOfCells();
3547 int spaceDim=getSpaceDimension();
3548 array->alloc(nbOfCells,spaceDim);
3549 double *pt=array->getPointer();
3550 const double *coo=getCoords()->getConstPointer();
3551 std::vector<int> conn;
3553 for(int i=0;i<nbOfCells;i++)
3556 getNodeIdsOfCell(i,conn);
3557 pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3559 ret->setArray(array);
3561 ret->synchronizeTimeWithSupport();
3566 * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3567 * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3568 * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3569 * from. If a result face is shared by two 3D cells, then the face in included twice in
3571 * \param [in] origin - 3 components of a point defining location of the plane.
3572 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3573 * must be greater than 1e-6.
3574 * \param [in] eps - half-thickness of the plane.
3575 * \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3576 * producing correspondent 2D cells. The caller is to delete this array
3577 * using decrRef() as it is no more needed.
3578 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3579 * not share the node coordinates array with \a this mesh. The caller is to
3580 * delete this mesh using decrRef() as it is no more needed.
3581 * \throw If the coordinates array is not set.
3582 * \throw If the nodal connectivity of cells is not defined.
3583 * \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3584 * \throw If magnitude of \a vec is less than 1e-6.
3585 * \throw If the plane does not intersect any 3D cell of \a this mesh.
3586 * \throw If \a this includes quadratic cells.
3588 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3590 checkFullyDefined();
3591 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3592 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3593 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3594 if(candidates->empty())
3595 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3596 std::vector<int> nodes;
3597 DataArrayInt *cellIds1D=0;
3598 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3599 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3600 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3601 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3602 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3603 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3604 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3605 revDesc2=0; revDescIndx2=0;
3606 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3607 revDesc1=0; revDescIndx1=0;
3608 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3609 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3611 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3612 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3614 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3615 std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3616 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3617 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3618 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3619 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3620 connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3621 subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3622 if(cellIds2->empty())
3623 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3624 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3625 ret->setCoords(mDesc1->getCoords());
3626 ret->setConnectivity(conn,connI,true);
3627 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3632 * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3633 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
3634 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3636 * \param [in] origin - 3 components of a point defining location of the plane.
3637 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3638 * must be greater than 1e-6.
3639 * \param [in] eps - half-thickness of the plane.
3640 * \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3641 * producing correspondent segments. The caller is to delete this array
3642 * using decrRef() as it is no more needed.
3643 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3644 * mesh in 3D space. This mesh does not share the node coordinates array with
3645 * \a this mesh. The caller is to delete this mesh using decrRef() as it is
3647 * \throw If the coordinates array is not set.
3648 * \throw If the nodal connectivity of cells is not defined.
3649 * \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3650 * \throw If magnitude of \a vec is less than 1e-6.
3651 * \throw If the plane does not intersect any 2D cell of \a this mesh.
3652 * \throw If \a this includes quadratic cells.
3654 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3656 checkFullyDefined();
3657 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3658 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3659 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3660 if(candidates->empty())
3661 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3662 std::vector<int> nodes;
3663 DataArrayInt *cellIds1D=0;
3664 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3665 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3666 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3667 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3668 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3669 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3670 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3671 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3672 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3674 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3675 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3677 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3678 int ncellsSub=subMesh->getNumberOfCells();
3679 std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3680 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3681 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3682 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3683 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3685 const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3686 const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3687 for(int i=0;i<ncellsSub;i++)
3689 if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3691 if(cut3DSurf[i].first!=-2)
3693 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3694 connI->pushBackSilent(conn->getNumberOfTuples());
3695 cellIds2->pushBackSilent(i);
3699 int cellId3DSurf=cut3DSurf[i].second;
3700 int offset=nodalI[cellId3DSurf]+1;
3701 int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3702 for(int j=0;j<nbOfEdges;j++)
3704 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3705 connI->pushBackSilent(conn->getNumberOfTuples());
3706 cellIds2->pushBackSilent(cellId3DSurf);
3711 if(cellIds2->empty())
3712 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3713 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3714 ret->setCoords(mDesc1->getCoords());
3715 ret->setConnectivity(conn,connI,true);
3716 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3721 * Finds cells whose bounding boxes intersect a given plane.
3722 * \param [in] origin - 3 components of a point defining location of the plane.
3723 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3724 * must be greater than 1e-6.
3725 * \param [in] eps - half-thickness of the plane.
3726 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3727 * cells. The caller is to delete this array using decrRef() as it is no more
3729 * \throw If the coordinates array is not set.
3730 * \throw If the nodal connectivity of cells is not defined.
3731 * \throw If \a this->getSpaceDimension() != 3.
3732 * \throw If magnitude of \a vec is less than 1e-6.
3733 * \sa buildSlice3D()
3735 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3737 checkFullyDefined();
3738 if(getSpaceDimension()!=3)
3739 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3740 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3742 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3744 vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3745 double angle=acos(vec[2]/normm);
3746 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3750 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3751 MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3752 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3754 mw->getBoundingBox(bbox);
3755 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3756 cellIds=mw->getCellsInBoundingBox(bbox,eps);
3760 getBoundingBox(bbox);
3761 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3762 cellIds=getCellsInBoundingBox(bbox,eps);
3764 return cellIds.retn();
3768 * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3769 * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3770 * No consideration of coordinate is done by this method.
3771 * 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)
3772 * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3774 bool MEDCouplingUMesh::isContiguous1D() const
3776 if(getMeshDimension()!=1)
3777 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3778 int nbCells=getNumberOfCells();
3780 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3781 const int *connI=_nodal_connec_index->getConstPointer();
3782 const int *conn=_nodal_connec->getConstPointer();
3783 int ref=conn[connI[0]+2];
3784 for(int i=1;i<nbCells;i++)
3786 if(conn[connI[i]+1]!=ref)
3788 ref=conn[connI[i]+2];
3794 * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3795 * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3796 * \param pt reference point of the line
3797 * \param v normalized director vector of the line
3798 * \param eps max precision before throwing an exception
3799 * \param res output of size this->getNumberOfCells
3801 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3803 if(getMeshDimension()!=1)
3804 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3805 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3806 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3807 if(getSpaceDimension()!=3)
3808 throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3809 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3810 const double *fPtr=f->getArray()->getConstPointer();
3812 for(int i=0;i<getNumberOfCells();i++)
3814 const double *tmp1=fPtr+3*i;
3815 tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3816 tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3817 tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3818 double n1=INTERP_KERNEL::norm<3>(tmp);
3819 n1/=INTERP_KERNEL::norm<3>(tmp1);
3821 throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3823 const double *coo=getCoords()->getConstPointer();
3824 for(int i=0;i<getNumberOfNodes();i++)
3826 std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3827 std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3828 res[i]=std::accumulate(tmp,tmp+3,0.);
3833 * 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.
3834 * \a this is expected to be a mesh so that its space dimension is equal to its
3835 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3836 * 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).
3838 * 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
3839 * 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).
3840 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3842 * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3843 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3845 * \param [in] ptBg the start pointer (included) of the coordinates of the point
3846 * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3847 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3848 * \return the positive value of the distance.
3849 * \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
3851 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3853 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
3855 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3856 if(meshDim!=spaceDim-1)
3857 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3858 if(meshDim!=2 && meshDim!=1)
3859 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3860 checkFullyDefined();
3861 if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3862 { 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()); }
3863 DataArrayInt *ret1=0;
3864 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
3865 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
3866 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
3867 cellId=*ret1Safe->begin();
3868 return *ret0->begin();
3872 * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
3873 * to \a this and the first \a cellId in \a this corresponding to the returned distance.
3874 * 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
3875 * 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).
3876 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3878 * \a this is expected to be a mesh so that its space dimension is equal to its
3879 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3880 * 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).
3882 * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
3883 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3885 * \param [in] pts the list of points in which each tuple represents a point
3886 * \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.
3887 * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
3888 * \throw if number of components of \a pts is not equal to the space dimension.
3889 * \throw if mesh dimension of \a this is not equal to space dimension - 1.
3890 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
3892 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
3895 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
3896 pts->checkAllocated();
3897 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3898 if(meshDim!=spaceDim-1)
3899 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
3900 if(meshDim!=2 && meshDim!=1)
3901 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
3902 if(pts->getNumberOfComponents()!=spaceDim)
3904 std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
3905 throw INTERP_KERNEL::Exception(oss.str().c_str());
3907 checkFullyDefined();
3908 int nbCells=getNumberOfCells();
3910 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
3911 int nbOfPts=pts->getNumberOfTuples();
3912 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
3913 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
3914 const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
3915 double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
3916 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
3917 const double *bbox(bboxArr->begin());
3922 BBTreeDst<3> myTree(bbox,0,0,nbCells);
3923 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
3925 double x=std::numeric_limits<double>::max();
3926 std::vector<int> elems;
3927 myTree.getMinDistanceOfMax(ptsPtr,x);
3928 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3929 DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3935 BBTreeDst<2> myTree(bbox,0,0,nbCells);
3936 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
3938 double x=std::numeric_limits<double>::max();
3939 std::vector<int> elems;
3940 myTree.getMinDistanceOfMax(ptsPtr,x);
3941 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3942 DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3947 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
3949 cellIds=ret1.retn();
3954 * \param [in] pt the start pointer (included) of the coordinates of the point
3955 * \param [in] cellIdsBg the start pointer (included) of cellIds
3956 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3957 * \param [in] nc nodal connectivity
3958 * \param [in] ncI nodal connectivity index
3959 * \param [in,out] ret0 the min distance between \a this and the external input point
3960 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3961 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
3963 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)
3966 ret0=std::numeric_limits<double>::max();
3967 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
3969 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
3971 case INTERP_KERNEL::NORM_TRI3:
3973 double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
3975 { ret0=tmp; cellId=*zeCell; }
3978 case INTERP_KERNEL::NORM_QUAD4:
3979 case INTERP_KERNEL::NORM_POLYGON:
3981 double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
3983 { ret0=tmp; cellId=*zeCell; }
3987 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
3993 * \param [in] pt the start pointer (included) of the coordinates of the point
3994 * \param [in] cellIdsBg the start pointer (included) of cellIds
3995 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3996 * \param [in] nc nodal connectivity
3997 * \param [in] ncI nodal connectivity index
3998 * \param [in,out] ret0 the min distance between \a this and the external input point
3999 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4000 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4002 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)
4005 ret0=std::numeric_limits<double>::max();
4006 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4008 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4010 case INTERP_KERNEL::NORM_SEG2:
4012 std::size_t uselessEntry=0;
4013 double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4016 { ret0=tmp; cellId=*zeCell; }
4020 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4026 * Finds cells in contact with a ball (i.e. a point with precision).
4027 * 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.
4028 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4030 * \warning This method is suitable if the caller intends to evaluate only one
4031 * point, for more points getCellsContainingPoints() is recommended as it is
4033 * \param [in] pos - array of coordinates of the ball central point.
4034 * \param [in] eps - ball radius.
4035 * \return int - a smallest id of cells being in contact with the ball, -1 in case
4036 * if there are no such cells.
4037 * \throw If the coordinates array is not set.
4038 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4040 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4042 std::vector<int> elts;
4043 getCellsContainingPoint(pos,eps,elts);
4046 return elts.front();
4050 * Finds cells in contact with a ball (i.e. a point with precision).
4051 * 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.
4052 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4053 * \warning This method is suitable if the caller intends to evaluate only one
4054 * point, for more points getCellsContainingPoints() is recommended as it is
4056 * \param [in] pos - array of coordinates of the ball central point.
4057 * \param [in] eps - ball radius.
4058 * \param [out] elts - vector returning ids of the found cells. It is cleared
4059 * before inserting ids.
4060 * \throw If the coordinates array is not set.
4061 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4063 * \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4064 * \ref py_mcumesh_getCellsContainingPoint "Here is a Python example".
4066 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4068 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4069 getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4070 elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4075 namespace ParaMEDMEM
4077 template<const int SPACEDIMM>
4081 static const int MY_SPACEDIM=SPACEDIMM;
4082 static const int MY_MESHDIM=8;
4083 typedef int MyConnType;
4084 static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4086 // useless, but for windows compilation ...
4087 const double* getCoordinatesPtr() const { return 0; }
4088 const int* getConnectivityPtr() const { return 0; }
4089 const int* getConnectivityIndexPtr() const { return 0; }
4090 INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4095 * Warning the nodes in \a m should be decrRefed ! To avoid that Node * pointer be replaced by another instance.
4097 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map<INTERP_KERNEL::Node *,int>& m)
4099 INTERP_KERNEL::Edge *ret=0;
4100 INTERP_KERNEL::Node *n0(new INTERP_KERNEL::Node(coords2D[2*bg[0]],coords2D[2*bg[0]+1])),*n1(new INTERP_KERNEL::Node(coords2D[2*bg[1]],coords2D[2*bg[1]+1]));
4101 m[n0]=bg[0]; m[n1]=bg[1];
4104 case INTERP_KERNEL::NORM_SEG2:
4106 ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4109 case INTERP_KERNEL::NORM_SEG3:
4111 INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4112 INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4113 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4114 // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4115 bool colinearity(inters.areColinears());
4116 delete e1; delete e2;
4118 { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4120 { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4124 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4129 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4131 INTERP_KERNEL::Edge *ret=0;
4134 case INTERP_KERNEL::NORM_SEG2:
4136 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4139 case INTERP_KERNEL::NORM_SEG3:
4141 INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4142 INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4143 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4144 // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4145 bool colinearity=inters.areColinears();
4146 delete e1; delete e2;
4148 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4150 ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4151 mapp2[bg[2]].second=false;
4155 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4161 * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4162 * the global mesh 'mDesc'.
4163 * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4164 * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4166 INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4167 std::map<INTERP_KERNEL::Node *,int>& mapp)
4168 throw(INTERP_KERNEL::Exception)
4171 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.
4172 const double *coo=mDesc->getCoords()->getConstPointer();
4173 const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4174 const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4176 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4177 s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4178 for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4180 INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4181 mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4183 INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4184 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4186 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4187 ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4189 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4191 if((*it2).second.second)
4192 mapp[(*it2).second.first]=(*it2).first;
4193 ((*it2).second.first)->decrRef();
4198 INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4202 int locId=nodeId-offset2;
4203 return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4207 int locId=nodeId-offset1;
4208 return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4210 return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4214 * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4216 void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4217 const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4218 /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4220 for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4222 int eltId1=abs(*desc1)-1;
4223 for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4225 std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4226 if(it==mappRev.end())
4228 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4239 template<int SPACEDIM>
4240 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4241 double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4243 elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4244 int *eltsIndexPtr(eltsIndex->getPointer());
4245 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4246 const double *bbox(bboxArr->begin());
4247 int nbOfCells=getNumberOfCells();
4248 const int *conn=_nodal_connec->getConstPointer();
4249 const int *connI=_nodal_connec_index->getConstPointer();
4250 double bb[2*SPACEDIM];
4251 BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4252 for(int i=0;i<nbOfPoints;i++)
4254 eltsIndexPtr[i+1]=eltsIndexPtr[i];
4255 for(int j=0;j<SPACEDIM;j++)
4257 bb[2*j]=pos[SPACEDIM*i+j];
4258 bb[2*j+1]=pos[SPACEDIM*i+j];
4260 std::vector<int> candidates;
4261 myTree.getIntersectingElems(bb,candidates);
4262 for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4264 int sz(connI[(*iter)+1]-connI[*iter]-1);
4265 INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4267 if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4268 status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4272 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4273 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4274 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4275 std::vector<INTERP_KERNEL::Node *> nodes(sz);
4276 INTERP_KERNEL::QuadraticPolygon *pol(0);
4277 for(int j=0;j<sz;j++)
4279 int nodeId(conn[connI[*iter]+1+j]);
4280 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4282 if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4283 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4285 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4286 INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4287 double a(0.),b(0.),c(0.);
4288 a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4289 status=pol->isInOrOut2(n);
4290 delete pol; n->decrRef();
4294 eltsIndexPtr[i+1]++;
4295 elts->pushBackSilent(*iter);
4301 * Finds cells in contact with several balls (i.e. points with precision).
4302 * This method is an extension of getCellContainingPoint() and
4303 * getCellsContainingPoint() for the case of multiple points.
4304 * 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.
4305 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4306 * \param [in] pos - an array of coordinates of points in full interlace mode :
4307 * X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4308 * this->getSpaceDimension() * \a nbOfPoints
4309 * \param [in] nbOfPoints - number of points to locate within \a this mesh.
4310 * \param [in] eps - radius of balls (i.e. the precision).
4311 * \param [out] elts - vector returning ids of found cells.
4312 * \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4313 * dividing cell ids in \a elts into groups each referring to one
4314 * point. Its every element (except the last one) is an index pointing to the
4315 * first id of a group of cells. For example cells in contact with the *i*-th
4316 * point are described by following range of indices:
4317 * [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4318 * \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4319 * Number of cells in contact with the *i*-th point is
4320 * \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4321 * \throw If the coordinates array is not set.
4322 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4324 * \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4325 * \ref py_mcumesh_getCellsContainingPoints "Here is a Python example".
4327 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4328 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4330 int spaceDim=getSpaceDimension();
4331 int mDim=getMeshDimension();
4336 const double *coords=_coords->getConstPointer();
4337 getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4344 throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4346 else if(spaceDim==2)
4350 const double *coords=_coords->getConstPointer();
4351 getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4354 throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4356 else if(spaceDim==1)
4360 const double *coords=_coords->getConstPointer();
4361 getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4364 throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4367 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4371 * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4372 * least two its edges intersect each other anywhere except their extremities. An
4373 * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4374 * \param [in,out] cells - a vector returning ids of the found cells. It is not
4375 * cleared before filling in.
4376 * \param [in] eps - precision.
4377 * \throw If \a this->getMeshDimension() != 2.
4378 * \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4380 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4382 const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4383 if(getMeshDimension()!=2)
4384 throw INTERP_KERNEL::Exception(msg);
4385 int spaceDim=getSpaceDimension();
4386 if(spaceDim!=2 && spaceDim!=3)
4387 throw INTERP_KERNEL::Exception(msg);
4388 const int *conn=_nodal_connec->getConstPointer();
4389 const int *connI=_nodal_connec_index->getConstPointer();
4390 int nbOfCells=getNumberOfCells();
4391 std::vector<double> cell2DinS2;
4392 for(int i=0;i<nbOfCells;i++)
4394 int offset=connI[i];
4395 int nbOfNodesForCell=connI[i+1]-offset-1;
4396 if(nbOfNodesForCell<=3)
4398 bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4399 project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4400 if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4407 * This method is typically requested to unbutterfly 2D linear cells in \b this.
4409 * 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.
4410 * 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.
4412 * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4413 * This convex envelop is computed using Jarvis march algorithm.
4414 * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4415 * 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)
4416 * 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.
4418 * \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.
4420 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4422 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4423 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D works only for meshDim=2 and spaceDim=2 !");
4424 checkFullyDefined();
4425 const double *coords=getCoords()->getConstPointer();
4426 int nbOfCells=getNumberOfCells();
4427 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4428 nodalConnecIndexOut->alloc(nbOfCells+1,1);
4429 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4430 int *workIndexOut=nodalConnecIndexOut->getPointer();
4432 const int *nodalConnecIn=_nodal_connec->getConstPointer();
4433 const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4434 std::set<INTERP_KERNEL::NormalizedCellType> types;
4435 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4436 isChanged->alloc(0,1);
4437 for(int i=0;i<nbOfCells;i++,workIndexOut++)
4439 int pos=nodalConnecOut->getNumberOfTuples();
4440 if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4441 isChanged->pushBackSilent(i);
4442 types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4443 workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4445 if(isChanged->empty())
4447 setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4449 return isChanged.retn();
4453 * This method is \b NOT const because it can modify \a this.
4454 * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4455 * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4456 * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4457 * \b 1 for translation and rotation around point of 'mesh1D'.
4458 * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.
4460 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4462 checkFullyDefined();
4463 mesh1D->checkFullyDefined();
4464 if(!mesh1D->isContiguous1D())
4465 throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4466 if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4467 throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4468 if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4469 throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4470 if(mesh1D->getMeshDimension()!=1)
4471 throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4473 if(isPresenceOfQuadratic())
4475 if(mesh1D->isFullyQuadratic())
4478 throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4481 int oldNbOfNodes=getNumberOfNodes();
4482 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4487 newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4492 newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4496 throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4498 setCoords(newCoords);
4499 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4505 * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4506 * If it is not the case an exception will be thrown.
4507 * This method is non const because the coordinate of \a this can be appended with some new points issued from
4508 * intersection of plane defined by ('origin','vec').
4509 * This method has one in/out parameter : 'cut3DCurve'.
4510 * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4511 * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4512 * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4513 * This method will throw an exception if \a this contains a non linear segment.
4515 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4517 checkFullyDefined();
4518 if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4519 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4520 int ncells=getNumberOfCells();
4521 int nnodes=getNumberOfNodes();
4522 double vec2[3],vec3[3],vec4[3];
4523 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4525 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4526 vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4527 const int *conn=_nodal_connec->getConstPointer();
4528 const int *connI=_nodal_connec_index->getConstPointer();
4529 const double *coo=_coords->getConstPointer();
4530 std::vector<double> addCoo;
4531 for(int i=0;i<ncells;i++)
4533 if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4535 if(cut3DCurve[i]==-2)
4537 int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4538 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];
4539 double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4540 double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4541 if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4543 const double *st2=coo+3*st;
4544 vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4545 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]));
4546 if(pos>eps && pos<1-eps)
4548 int nNode=((int)addCoo.size())/3;
4549 vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4550 addCoo.insert(addCoo.end(),vec4,vec4+3);
4551 cut3DCurve[i]=nnodes+nNode;
4557 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4561 int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4562 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4563 coo2->alloc(newNbOfNodes,3);
4564 double *tmp=coo2->getPointer();
4565 tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4566 std::copy(addCoo.begin(),addCoo.end(),tmp);
4567 DataArrayDouble::SetArrayIn(coo2,_coords);
4572 * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4573 * \param mesh1D is the input 1D mesh used for translation computation.
4574 * \return newCoords new coords filled by this method.
4576 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4578 int oldNbOfNodes=getNumberOfNodes();
4579 int nbOf1DCells=mesh1D->getNumberOfCells();
4580 int spaceDim=getSpaceDimension();
4581 DataArrayDouble *ret=DataArrayDouble::New();
4582 std::vector<bool> isQuads;
4583 int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4584 ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4585 double *retPtr=ret->getPointer();
4586 const double *coords=getCoords()->getConstPointer();
4587 double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4589 std::vector<double> c;
4593 for(int i=0;i<nbOf1DCells;i++)
4596 mesh1D->getNodeIdsOfCell(i,v);
4598 mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4599 mesh1D->getCoordinatesOfNode(v[0],c);
4600 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4601 for(int j=0;j<oldNbOfNodes;j++)
4602 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4606 mesh1D->getCoordinatesOfNode(v[1],c);
4607 mesh1D->getCoordinatesOfNode(v[0],c);
4608 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4609 for(int j=0;j<oldNbOfNodes;j++)
4610 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4613 ret->copyStringInfoFrom(*getCoords());
4618 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4619 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4620 * \return newCoords new coords filled by this method.
4622 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4624 if(mesh1D->getSpaceDimension()==2)
4625 return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4626 if(mesh1D->getSpaceDimension()==3)
4627 return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4628 throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4632 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4633 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4634 * \return newCoords new coords filled by this method.
4636 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4639 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4640 int oldNbOfNodes=getNumberOfNodes();
4641 int nbOf1DCells=mesh1D->getNumberOfCells();
4643 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4644 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4645 int nbOfLevsInVec=nbOf1DCells+1;
4646 ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4647 double *retPtr=ret->getPointer();
4648 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4649 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4650 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4651 tmp->setCoords(tmp2);
4652 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4653 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4654 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4655 for(int i=1;i<nbOfLevsInVec;i++)
4657 const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4658 const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4659 const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4660 const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4661 tmp->translate(vec);
4662 double tmp3[2],radius,alpha,alpha0;
4663 const double *p0=i+1<nbOfLevsInVec?begin:third;
4664 const double *p1=i+1<nbOfLevsInVec?end:begin;
4665 const double *p2=i+1<nbOfLevsInVec?third:end;
4666 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4667 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]);
4668 double angle=acos(cosangle/(radius*radius));
4669 tmp->rotate(end,0,angle);
4670 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4676 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4677 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4678 * \return newCoords new coords filled by this method.
4680 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4683 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4684 int oldNbOfNodes=getNumberOfNodes();
4685 int nbOf1DCells=mesh1D->getNumberOfCells();
4687 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4688 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4689 int nbOfLevsInVec=nbOf1DCells+1;
4690 ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4691 double *retPtr=ret->getPointer();
4692 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4693 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4694 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4695 tmp->setCoords(tmp2);
4696 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4697 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4698 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4699 for(int i=1;i<nbOfLevsInVec;i++)
4701 const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4702 const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4703 const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4704 const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4705 tmp->translate(vec);
4706 double tmp3[2],radius,alpha,alpha0;
4707 const double *p0=i+1<nbOfLevsInVec?begin:third;
4708 const double *p1=i+1<nbOfLevsInVec?end:begin;
4709 const double *p2=i+1<nbOfLevsInVec?third:end;
4710 double vecPlane[3]={
4711 (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4712 (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4713 (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4715 double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4718 vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4719 double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4720 double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4722 double c2=cos(asin(s2));
4724 {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4725 {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4726 {-vec2[1]*s2, vec2[0]*s2, c2}
4728 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]};
4729 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]};
4730 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]};
4731 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4732 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]);
4733 double angle=acos(cosangle/(radius*radius));
4734 tmp->rotate(end,vecPlane,angle);
4737 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4743 * This method is private because not easy to use for end user. This method is const contrary to
4744 * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4745 * the coords sorted slice by slice.
4746 * \param isQuad specifies presence of quadratic cells.
4748 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4750 int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4751 int nbOf2DCells=getNumberOfCells();
4752 int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4753 MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4754 const int *conn=_nodal_connec->getConstPointer();
4755 const int *connI=_nodal_connec_index->getConstPointer();
4756 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4757 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4758 newConnI->alloc(nbOf3DCells+1,1);
4759 int *newConnIPtr=newConnI->getPointer();
4761 std::vector<int> newc;
4762 for(int j=0;j<nbOf2DCells;j++)
4764 AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4765 *newConnIPtr++=(int)newc.size();
4767 newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4768 int *newConnPtr=newConn->getPointer();
4769 int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4770 newConnIPtr=newConnI->getPointer();
4771 for(int iz=0;iz<nbOf1DCells;iz++)
4774 std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4775 for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4777 int icell=(int)(iter-newc.begin());
4778 if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4781 *newConnPtr=(*iter)+iz*deltaPerLev;
4786 *newConnPtr=(*iter);
4789 ret->setConnectivity(newConn,newConnI,true);
4790 ret->setCoords(getCoords());
4795 * Checks if \a this mesh is constituted by only quadratic cells.
4796 * \return bool - \c true if there are only quadratic cells in \a this mesh.
4797 * \throw If the coordinates array is not set.
4798 * \throw If the nodal connectivity of cells is not defined.
4800 bool MEDCouplingUMesh::isFullyQuadratic() const
4802 checkFullyDefined();
4804 int nbOfCells=getNumberOfCells();
4805 for(int i=0;i<nbOfCells && ret;i++)
4807 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4808 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4809 ret=cm.isQuadratic();
4815 * Checks if \a this mesh includes any quadratic cell.
4816 * \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4817 * \throw If the coordinates array is not set.
4818 * \throw If the nodal connectivity of cells is not defined.
4820 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4822 checkFullyDefined();
4824 int nbOfCells=getNumberOfCells();
4825 for(int i=0;i<nbOfCells && !ret;i++)
4827 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4828 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4829 ret=cm.isQuadratic();
4835 * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4836 * this mesh, it remains unchanged.
4837 * \throw If the coordinates array is not set.
4838 * \throw If the nodal connectivity of cells is not defined.
4840 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4842 checkFullyDefined();
4843 int nbOfCells=getNumberOfCells();
4845 const int *iciptr=_nodal_connec_index->getConstPointer();
4846 for(int i=0;i<nbOfCells;i++)
4848 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4849 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4850 if(cm.isQuadratic())
4852 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4853 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4854 if(!cml.isDynamic())
4855 delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4857 delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4862 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4863 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4864 const int *icptr=_nodal_connec->getConstPointer();
4865 newConn->alloc(getMeshLength()-delta,1);
4866 newConnI->alloc(nbOfCells+1,1);
4867 int *ocptr=newConn->getPointer();
4868 int *ociptr=newConnI->getPointer();
4871 for(int i=0;i<nbOfCells;i++,ociptr++)
4873 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4874 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4875 if(!cm.isQuadratic())
4877 _types.insert(type);
4878 ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4879 ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4883 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4884 _types.insert(typel);
4885 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4886 int newNbOfNodes=cml.getNumberOfNodes();
4888 newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4889 *ocptr++=(int)typel;
4890 ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4891 ociptr[1]=ociptr[0]+newNbOfNodes+1;
4894 setConnectivity(newConn,newConnI,false);
4898 * This method converts all linear cell in \a this to quadratic one.
4899 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4900 * 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)
4901 * 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.
4902 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4903 * end of the existing coordinates.
4905 * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4906 * corresponding quadratic cells. 1 is those creating the 'most' complex.
4907 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4909 * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4911 * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4913 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
4915 DataArrayInt *conn=0,*connI=0;
4916 DataArrayDouble *coords=0;
4917 std::set<INTERP_KERNEL::NormalizedCellType> types;
4918 checkFullyDefined();
4919 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
4920 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
4921 int meshDim=getMeshDimension();
4922 switch(conversionType)
4928 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4929 connSafe=conn; connISafe=connI; coordsSafe=coords;
4932 ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4933 connSafe=conn; connISafe=connI; coordsSafe=coords;
4936 ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
4937 connSafe=conn; connISafe=connI; coordsSafe=coords;
4940 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
4948 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
4949 connSafe=conn; connISafe=connI; coordsSafe=coords;
4952 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
4953 connSafe=conn; connISafe=connI; coordsSafe=coords;
4956 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
4957 connSafe=conn; connISafe=connI; coordsSafe=coords;
4960 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
4965 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
4967 setConnectivity(connSafe,connISafe,false);
4969 setCoords(coordsSafe);
4974 * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4975 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4976 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4978 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
4980 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4981 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4982 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4983 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4984 int nbOfCells=getNumberOfCells();
4985 int nbOfNodes=getNumberOfNodes();
4986 const int *cPtr=_nodal_connec->getConstPointer();
4987 const int *icPtr=_nodal_connec_index->getConstPointer();
4988 int lastVal=0,offset=nbOfNodes;
4989 for(int i=0;i<nbOfCells;i++,icPtr++)
4991 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4992 if(type==INTERP_KERNEL::NORM_SEG2)
4994 types.insert(INTERP_KERNEL::NORM_SEG3);
4995 newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
4996 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
4997 newConn->pushBackSilent(offset++);
4999 newConnI->pushBackSilent(lastVal);
5000 ret->pushBackSilent(i);
5005 lastVal+=(icPtr[1]-icPtr[0]);
5006 newConnI->pushBackSilent(lastVal);
5007 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5010 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5011 coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5015 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
5017 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5018 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5019 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5021 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5022 DataArrayInt *conn1D=0,*conn1DI=0;
5023 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5024 DataArrayDouble *coordsTmp=0;
5025 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5026 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5027 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5028 const int *c1DPtr=conn1D->begin();
5029 const int *c1DIPtr=conn1DI->begin();
5030 int nbOfCells=getNumberOfCells();
5031 const int *cPtr=_nodal_connec->getConstPointer();
5032 const int *icPtr=_nodal_connec_index->getConstPointer();
5034 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5036 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5037 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5038 if(!cm.isQuadratic())
5040 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5041 types.insert(typ2); newConn->pushBackSilent(typ2);
5042 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5043 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5044 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5045 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5046 newConnI->pushBackSilent(lastVal);
5047 ret->pushBackSilent(i);
5052 lastVal+=(icPtr[1]-icPtr[0]);
5053 newConnI->pushBackSilent(lastVal);
5054 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5057 conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5062 * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5063 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5064 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5066 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5069 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5070 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5071 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5074 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5076 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5077 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5079 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5080 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5081 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5083 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5084 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5085 DataArrayInt *conn1D=0,*conn1DI=0;
5086 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5087 DataArrayDouble *coordsTmp=0;
5088 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5089 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5090 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5091 const int *c1DPtr=conn1D->begin();
5092 const int *c1DIPtr=conn1DI->begin();
5093 int nbOfCells=getNumberOfCells();
5094 const int *cPtr=_nodal_connec->getConstPointer();
5095 const int *icPtr=_nodal_connec_index->getConstPointer();
5096 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5097 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5099 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5100 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5101 if(!cm.isQuadratic())
5103 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5104 types.insert(typ2); newConn->pushBackSilent(typ2);
5105 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5106 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5107 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5108 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5109 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5110 newConnI->pushBackSilent(lastVal);
5111 ret->pushBackSilent(i);
5116 lastVal+=(icPtr[1]-icPtr[0]);
5117 newConnI->pushBackSilent(lastVal);
5118 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5121 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5122 coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5127 * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5128 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5129 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5131 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5133 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5134 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5135 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5138 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5140 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5141 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5142 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5143 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5145 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5146 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5147 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5149 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5150 const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5151 DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5152 std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5153 DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5154 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5155 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5156 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5157 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5158 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5159 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5160 const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5161 int nbOfCells=getNumberOfCells();
5162 const int *cPtr=_nodal_connec->getConstPointer();
5163 const int *icPtr=_nodal_connec_index->getConstPointer();
5164 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5165 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5167 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5168 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5169 if(!cm.isQuadratic())
5171 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5172 if(typ2==INTERP_KERNEL::NORM_ERROR)
5174 std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5175 throw INTERP_KERNEL::Exception(oss.str().c_str());
5177 types.insert(typ2); newConn->pushBackSilent(typ2);
5178 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5179 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5180 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5181 for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5183 int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5184 int tmpPos=newConn->getNumberOfTuples();
5185 newConn->pushBackSilent(nodeId2);
5186 ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5188 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5189 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5190 newConnI->pushBackSilent(lastVal);
5191 ret->pushBackSilent(i);
5196 lastVal+=(icPtr[1]-icPtr[0]);
5197 newConnI->pushBackSilent(lastVal);
5198 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5201 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5202 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5203 coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5204 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5205 std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5206 int *c=newConn->getPointer();
5207 const int *cI(newConnI->begin());
5208 for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5209 c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5210 offset=coordsTmp2Safe->getNumberOfTuples();
5211 for(const int *elt=ret->begin();elt!=ret->end();elt++)
5212 c[cI[(*elt)+1]-1]+=offset;
5213 coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5218 * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5219 * so that the number of cells remains the same. Quadratic faces are converted to
5220 * polygons. This method works only for 2D meshes in
5221 * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5222 * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5223 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5224 * \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5225 * a polylinized edge constituting the input polygon.
5226 * \throw If the coordinates array is not set.
5227 * \throw If the nodal connectivity of cells is not defined.
5228 * \throw If \a this->getMeshDimension() != 2.
5229 * \throw If \a this->getSpaceDimension() != 2.
5231 void MEDCouplingUMesh::tessellate2D(double eps)
5233 checkFullyDefined();
5234 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
5235 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5236 double epsa=fabs(eps);
5237 if(epsa<std::numeric_limits<double>::min())
5238 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 !");
5239 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5240 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5241 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5242 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5243 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5244 revDesc1=0; revDescIndx1=0;
5245 mDesc->tessellate2DCurve(eps);
5246 subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5247 setCoords(mDesc->getCoords());
5251 * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5252 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5253 * \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5254 * a sub-divided edge.
5255 * \throw If the coordinates array is not set.
5256 * \throw If the nodal connectivity of cells is not defined.
5257 * \throw If \a this->getMeshDimension() != 1.
5258 * \throw If \a this->getSpaceDimension() != 2.
5260 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5262 checkFullyDefined();
5263 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5264 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5265 double epsa=fabs(eps);
5266 if(epsa<std::numeric_limits<double>::min())
5267 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 !");
5268 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5269 int nbCells=getNumberOfCells();
5270 int nbNodes=getNumberOfNodes();
5271 const int *conn=_nodal_connec->getConstPointer();
5272 const int *connI=_nodal_connec_index->getConstPointer();
5273 const double *coords=_coords->getConstPointer();
5274 std::vector<double> addCoo;
5275 std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5276 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5277 newConnI->alloc(nbCells+1,1);
5278 int *newConnIPtr=newConnI->getPointer();
5281 INTERP_KERNEL::Node *tmp2[3];
5282 std::set<INTERP_KERNEL::NormalizedCellType> types;
5283 for(int i=0;i<nbCells;i++,newConnIPtr++)
5285 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5286 if(cm.isQuadratic())
5287 {//assert(connI[i+1]-connI[i]-1==3)
5288 tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5289 tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5290 tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5291 tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5292 INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5295 eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5296 types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5298 newConnIPtr[1]=(int)newConn.size();
5302 types.insert(INTERP_KERNEL::NORM_SEG2);
5303 newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5304 newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5305 newConnIPtr[1]=newConnIPtr[0]+3;
5310 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5311 newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5312 newConnIPtr[1]=newConnIPtr[0]+3;
5315 if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5318 DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5319 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5320 newConnArr->alloc((int)newConn.size(),1);
5321 std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5322 DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5323 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5324 newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5325 double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5326 std::copy(addCoo.begin(),addCoo.end(),work);
5327 DataArrayDouble::SetArrayIn(newCoords,_coords);
5332 * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5333 * In addition, returns an array mapping new cells to old ones. <br>
5334 * This method typically increases the number of cells in \a this mesh
5335 * but the number of nodes remains \b unchanged.
5336 * That's why the 3D splitting policies
5337 * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5338 * \param [in] policy - specifies a pattern used for splitting.
5339 * The semantic of \a policy is:
5340 * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5341 * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5342 * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8 into 5 TETRA4 (for 3D mesh only).
5343 * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8 into 6 TETRA4 (for 3D mesh only).
5344 * \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5345 * an id of old cell producing it. The caller is to delete this array using
5346 * decrRef() as it is no more needed.
5347 * \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5348 * \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5349 * and \a this->getMeshDimension() != 3.
5350 * \throw If \a policy is not one of the four discussed above.
5351 * \throw If the nodal connectivity of cells is not defined.
5352 * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5354 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5359 return simplexizePol0();
5361 return simplexizePol1();
5362 case (int) INTERP_KERNEL::PLANAR_FACE_5:
5363 return simplexizePlanarFace5();
5364 case (int) INTERP_KERNEL::PLANAR_FACE_6:
5365 return simplexizePlanarFace6();
5367 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)");
5372 * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5373 * - 1D: INTERP_KERNEL::NORM_SEG2
5374 * - 2D: INTERP_KERNEL::NORM_TRI3
5375 * - 3D: INTERP_KERNEL::NORM_TETRA4.
5377 * This method is useful for users that need to use P1 field services as
5378 * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5379 * All these methods need mesh support containing only simplex cells.
5380 * \return bool - \c true if there are only simplex cells in \a this mesh.
5381 * \throw If the coordinates array is not set.
5382 * \throw If the nodal connectivity of cells is not defined.
5383 * \throw If \a this->getMeshDimension() < 1.
5385 bool MEDCouplingUMesh::areOnlySimplexCells() const
5387 checkFullyDefined();
5388 int mdim=getMeshDimension();
5389 if(mdim<1 || mdim>3)
5390 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5391 int nbCells=getNumberOfCells();
5392 const int *conn=_nodal_connec->getConstPointer();
5393 const int *connI=_nodal_connec_index->getConstPointer();
5394 for(int i=0;i<nbCells;i++)
5396 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5404 * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5406 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5408 checkConnectivityFullyDefined();
5409 if(getMeshDimension()!=2)
5410 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5411 int nbOfCells=getNumberOfCells();
5412 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5413 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5414 ret->alloc(nbOfCells+nbOfCutCells,1);
5415 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5416 int *retPt=ret->getPointer();
5417 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5418 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5419 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5420 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5421 int *pt=newConn->getPointer();
5422 int *ptI=newConnI->getPointer();
5424 const int *oldc=_nodal_connec->getConstPointer();
5425 const int *ci=_nodal_connec_index->getConstPointer();
5426 for(int i=0;i<nbOfCells;i++,ci++)
5428 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5430 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5431 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5432 pt=std::copy(tmp,tmp+8,pt);
5441 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5442 ptI[1]=ptI[0]+ci[1]-ci[0];
5447 _nodal_connec->decrRef();
5448 _nodal_connec=newConn.retn();
5449 _nodal_connec_index->decrRef();
5450 _nodal_connec_index=newConnI.retn();
5457 * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5459 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5461 checkConnectivityFullyDefined();
5462 if(getMeshDimension()!=2)
5463 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5464 int nbOfCells=getNumberOfCells();
5465 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5466 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5467 ret->alloc(nbOfCells+nbOfCutCells,1);
5468 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5469 int *retPt=ret->getPointer();
5470 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5471 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5472 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5473 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5474 int *pt=newConn->getPointer();
5475 int *ptI=newConnI->getPointer();
5477 const int *oldc=_nodal_connec->getConstPointer();
5478 const int *ci=_nodal_connec_index->getConstPointer();
5479 for(int i=0;i<nbOfCells;i++,ci++)
5481 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5483 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5484 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5485 pt=std::copy(tmp,tmp+8,pt);
5494 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5495 ptI[1]=ptI[0]+ci[1]-ci[0];
5500 _nodal_connec->decrRef();
5501 _nodal_connec=newConn.retn();
5502 _nodal_connec_index->decrRef();
5503 _nodal_connec_index=newConnI.retn();
5510 * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5512 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5514 checkConnectivityFullyDefined();
5515 if(getMeshDimension()!=3)
5516 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5517 int nbOfCells=getNumberOfCells();
5518 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5519 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5520 ret->alloc(nbOfCells+4*nbOfCutCells,1);
5521 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5522 int *retPt=ret->getPointer();
5523 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5524 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5525 newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5526 newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5527 int *pt=newConn->getPointer();
5528 int *ptI=newConnI->getPointer();
5530 const int *oldc=_nodal_connec->getConstPointer();
5531 const int *ci=_nodal_connec_index->getConstPointer();
5532 for(int i=0;i<nbOfCells;i++,ci++)
5534 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5536 for(int j=0;j<5;j++,pt+=5,ptI++)
5538 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5539 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];
5546 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5547 ptI[1]=ptI[0]+ci[1]-ci[0];
5552 _nodal_connec->decrRef();
5553 _nodal_connec=newConn.retn();
5554 _nodal_connec_index->decrRef();
5555 _nodal_connec_index=newConnI.retn();
5562 * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5564 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5566 checkConnectivityFullyDefined();
5567 if(getMeshDimension()!=3)
5568 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5569 int nbOfCells=getNumberOfCells();
5570 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5571 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5572 ret->alloc(nbOfCells+5*nbOfCutCells,1);
5573 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5574 int *retPt=ret->getPointer();
5575 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5576 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5577 newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5578 newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5579 int *pt=newConn->getPointer();
5580 int *ptI=newConnI->getPointer();
5582 const int *oldc=_nodal_connec->getConstPointer();
5583 const int *ci=_nodal_connec_index->getConstPointer();
5584 for(int i=0;i<nbOfCells;i++,ci++)
5586 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5588 for(int j=0;j<6;j++,pt+=5,ptI++)
5590 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5591 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];
5598 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5599 ptI[1]=ptI[0]+ci[1]-ci[0];
5604 _nodal_connec->decrRef();
5605 _nodal_connec=newConn.retn();
5606 _nodal_connec_index->decrRef();
5607 _nodal_connec_index=newConnI.retn();
5614 * 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.
5615 * This method completly ignore coordinates.
5616 * \param nodeSubdived is the nodal connectivity of subdivision of edges
5617 * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5618 * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5619 * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5621 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5623 checkFullyDefined();
5624 if(getMeshDimension()!=2)
5625 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5626 int nbOfCells=getNumberOfCells();
5627 int *connI=_nodal_connec_index->getPointer();
5629 for(int i=0;i<nbOfCells;i++,connI++)
5631 int offset=descIndex[i];
5632 int nbOfEdges=descIndex[i+1]-offset;
5634 bool ddirect=desc[offset+nbOfEdges-1]>0;
5635 int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5636 int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5637 for(int j=0;j<nbOfEdges;j++)
5639 bool direct=desc[offset+j]>0;
5640 int edgeId=std::abs(desc[offset+j])-1;
5641 if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5643 int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5644 int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5645 int ref2=direct?id1:id2;
5648 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5649 newConnLgth+=nbOfSubNodes-1;
5654 std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5655 throw INTERP_KERNEL::Exception(oss.str().c_str());
5660 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5663 newConnLgth++;//+1 is for cell type
5664 connI[1]=newConnLgth;
5667 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5668 newConn->alloc(newConnLgth,1);
5669 int *work=newConn->getPointer();
5670 for(int i=0;i<nbOfCells;i++)
5672 *work++=INTERP_KERNEL::NORM_POLYGON;
5673 int offset=descIndex[i];
5674 int nbOfEdges=descIndex[i+1]-offset;
5675 for(int j=0;j<nbOfEdges;j++)
5677 bool direct=desc[offset+j]>0;
5678 int edgeId=std::abs(desc[offset+j])-1;
5680 work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5683 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5684 std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5685 work=std::copy(it,it+nbOfSubNodes-1,work);
5689 DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5692 _types.insert(INTERP_KERNEL::NORM_POLYGON);
5696 * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5697 * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5698 * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5699 * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5700 * so it can be useful to call mergeNodes() before calling this method.
5701 * \throw If \a this->getMeshDimension() <= 1.
5702 * \throw If the coordinates array is not set.
5703 * \throw If the nodal connectivity of cells is not defined.
5705 void MEDCouplingUMesh::convertDegeneratedCells()
5707 checkFullyDefined();
5708 if(getMeshDimension()<=1)
5709 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5710 int nbOfCells=getNumberOfCells();
5713 int initMeshLgth=getMeshLength();
5714 int *conn=_nodal_connec->getPointer();
5715 int *index=_nodal_connec_index->getPointer();
5719 for(int i=0;i<nbOfCells;i++)
5721 lgthOfCurCell=index[i+1]-posOfCurCell;
5722 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5724 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5725 conn+newPos+1,newLgth);
5726 conn[newPos]=newType;
5728 posOfCurCell=index[i+1];
5731 if(newPos!=initMeshLgth)
5732 _nodal_connec->reAlloc(newPos);
5737 * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5738 * A cell is considered to be oriented correctly if an angle between its
5739 * normal vector and a given vector is less than \c PI / \c 2.
5740 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5742 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5744 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5745 * is not cleared before filling in.
5746 * \throw If \a this->getMeshDimension() != 2.
5747 * \throw If \a this->getSpaceDimension() != 3.
5749 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5750 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5752 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
5754 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5755 throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5756 int nbOfCells=getNumberOfCells();
5757 const int *conn=_nodal_connec->getConstPointer();
5758 const int *connI=_nodal_connec_index->getConstPointer();
5759 const double *coordsPtr=_coords->getConstPointer();
5760 for(int i=0;i<nbOfCells;i++)
5762 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5763 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5765 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5766 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5773 * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5774 * considered to be oriented correctly if an angle between its normal vector and a
5775 * given vector is less than \c PI / \c 2.
5776 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5778 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5780 * \throw If \a this->getMeshDimension() != 2.
5781 * \throw If \a this->getSpaceDimension() != 3.
5783 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5784 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5786 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
5788 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5789 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5790 int nbOfCells=getNumberOfCells();
5791 int *conn=_nodal_connec->getPointer();
5792 const int *connI=_nodal_connec_index->getConstPointer();
5793 const double *coordsPtr=_coords->getConstPointer();
5794 bool isModified=false;
5795 for(int i=0;i<nbOfCells;i++)
5797 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5798 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5800 bool isQuadratic(INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic());
5801 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5806 std::vector<int> tmp(connI[i+1]-connI[i]-2);
5807 std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5808 std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5812 int sz(((int)(connI[i+1]-connI[i]-1))/2);
5813 std::vector<int> tmp0(sz-1),tmp1(sz);
5814 std::copy(conn+connI[i]+2,conn+connI[i]+1+sz,tmp0.rbegin());
5815 std::copy(conn+connI[i]+1+sz,conn+connI[i+1],tmp1.rbegin());
5816 std::copy(tmp0.begin(),tmp0.end(),conn+connI[i]+2);
5817 std::copy(tmp1.begin(),tmp1.end(),conn+connI[i]+1+sz);
5823 _nodal_connec->declareAsNew();
5828 * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5829 * oriented facets. The normal vector of the facet should point out of the cell.
5830 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5831 * is not cleared before filling in.
5832 * \throw If \a this->getMeshDimension() != 3.
5833 * \throw If \a this->getSpaceDimension() != 3.
5834 * \throw If the coordinates array is not set.
5835 * \throw If the nodal connectivity of cells is not defined.
5837 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5838 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5840 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
5842 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5843 throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5844 int nbOfCells=getNumberOfCells();
5845 const int *conn=_nodal_connec->getConstPointer();
5846 const int *connI=_nodal_connec_index->getConstPointer();
5847 const double *coordsPtr=_coords->getConstPointer();
5848 for(int i=0;i<nbOfCells;i++)
5850 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5851 if(type==INTERP_KERNEL::NORM_POLYHED)
5853 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5860 * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
5862 * \throw If \a this->getMeshDimension() != 3.
5863 * \throw If \a this->getSpaceDimension() != 3.
5864 * \throw If the coordinates array is not set.
5865 * \throw If the nodal connectivity of cells is not defined.
5866 * \throw If the reparation fails.
5868 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5869 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5870 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5872 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
5874 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5875 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
5876 int nbOfCells=getNumberOfCells();
5877 int *conn=_nodal_connec->getPointer();
5878 const int *connI=_nodal_connec_index->getConstPointer();
5879 const double *coordsPtr=_coords->getConstPointer();
5880 for(int i=0;i<nbOfCells;i++)
5882 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5883 if(type==INTERP_KERNEL::NORM_POLYHED)
5887 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5888 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5890 catch(INTERP_KERNEL::Exception& e)
5892 std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
5893 throw INTERP_KERNEL::Exception(oss.str().c_str());
5901 * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
5902 * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
5903 * according to which the first facet of the cell should be oriented to have the normal vector
5904 * pointing out of cell.
5905 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
5906 * cells. The caller is to delete this array using decrRef() as it is no more
5908 * \throw If \a this->getMeshDimension() != 3.
5909 * \throw If \a this->getSpaceDimension() != 3.
5910 * \throw If the coordinates array is not set.
5911 * \throw If the nodal connectivity of cells is not defined.
5913 * \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
5914 * \ref py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
5915 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5917 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
5919 const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
5920 if(getMeshDimension()!=3)
5921 throw INTERP_KERNEL::Exception(msg);
5922 int spaceDim=getSpaceDimension();
5924 throw INTERP_KERNEL::Exception(msg);
5926 int nbOfCells=getNumberOfCells();
5927 int *conn=_nodal_connec->getPointer();
5928 const int *connI=_nodal_connec_index->getConstPointer();
5929 const double *coo=getCoords()->getConstPointer();
5930 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
5931 for(int i=0;i<nbOfCells;i++)
5933 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5934 if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
5936 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
5938 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5939 cells->pushBackSilent(i);
5943 return cells.retn();
5947 * This method is a faster method to correct orientation of all 3D cells in \a this.
5948 * 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.
5949 * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
5951 * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
5952 * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons,
5954 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
5956 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5957 throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
5958 int nbOfCells=getNumberOfCells();
5959 int *conn=_nodal_connec->getPointer();
5960 const int *connI=_nodal_connec_index->getConstPointer();
5961 const double *coordsPtr=_coords->getConstPointer();
5962 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5963 for(int i=0;i<nbOfCells;i++)
5965 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5968 case INTERP_KERNEL::NORM_TETRA4:
5970 if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5972 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
5973 ret->pushBackSilent(i);
5977 case INTERP_KERNEL::NORM_PYRA5:
5979 if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5981 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
5982 ret->pushBackSilent(i);
5986 case INTERP_KERNEL::NORM_PENTA6:
5987 case INTERP_KERNEL::NORM_HEXA8:
5988 case INTERP_KERNEL::NORM_HEXGP12:
5990 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5992 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5993 ret->pushBackSilent(i);
5997 case INTERP_KERNEL::NORM_POLYHED:
5999 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6001 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6002 ret->pushBackSilent(i);
6007 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 !");
6015 * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6016 * If it is not the case an exception will be thrown.
6017 * This method is fast because the first cell of \a this is used to compute the plane.
6018 * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6019 * \param pos output of size at least 3 used to store a point owned of searched plane.
6021 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6023 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6024 throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6025 const int *conn=_nodal_connec->getConstPointer();
6026 const int *connI=_nodal_connec_index->getConstPointer();
6027 const double *coordsPtr=_coords->getConstPointer();
6028 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6029 std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6033 * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6034 * cells. Currently cells of the following types are treated:
6035 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6036 * For a cell of other type an exception is thrown.
6037 * Space dimension of a 2D mesh can be either 2 or 3.
6038 * The Edge Ratio of a cell \f$t\f$ is:
6039 * \f$\frac{|t|_\infty}{|t|_0}\f$,
6040 * where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6041 * the smallest edge lengths of \f$t\f$.
6042 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6043 * cells and one time, lying on \a this mesh. The caller is to delete this
6044 * field using decrRef() as it is no more needed.
6045 * \throw If the coordinates array is not set.
6046 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6047 * \throw If the connectivity data array has more than one component.
6048 * \throw If the connectivity data array has a named component.
6049 * \throw If the connectivity index data array has more than one component.
6050 * \throw If the connectivity index data array has a named component.
6051 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6052 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6053 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6055 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6058 int spaceDim=getSpaceDimension();
6059 int meshDim=getMeshDimension();
6060 if(spaceDim!=2 && spaceDim!=3)
6061 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6062 if(meshDim!=2 && meshDim!=3)
6063 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6064 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6066 int nbOfCells=getNumberOfCells();
6067 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6068 arr->alloc(nbOfCells,1);
6069 double *pt=arr->getPointer();
6070 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6071 const int *conn=_nodal_connec->getConstPointer();
6072 const int *connI=_nodal_connec_index->getConstPointer();
6073 const double *coo=_coords->getConstPointer();
6075 for(int i=0;i<nbOfCells;i++,pt++)
6077 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6080 case INTERP_KERNEL::NORM_TRI3:
6082 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6083 *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6086 case INTERP_KERNEL::NORM_QUAD4:
6088 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6089 *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6092 case INTERP_KERNEL::NORM_TETRA4:
6094 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6095 *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6099 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6101 conn+=connI[i+1]-connI[i];
6103 ret->setName("EdgeRatio");
6104 ret->synchronizeTimeWithSupport();
6109 * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6110 * cells. Currently cells of the following types are treated:
6111 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6112 * For a cell of other type an exception is thrown.
6113 * Space dimension of a 2D mesh can be either 2 or 3.
6114 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6115 * cells and one time, lying on \a this mesh. The caller is to delete this
6116 * field using decrRef() as it is no more needed.
6117 * \throw If the coordinates array is not set.
6118 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6119 * \throw If the connectivity data array has more than one component.
6120 * \throw If the connectivity data array has a named component.
6121 * \throw If the connectivity index data array has more than one component.
6122 * \throw If the connectivity index data array has a named component.
6123 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6124 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6125 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6127 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6130 int spaceDim=getSpaceDimension();
6131 int meshDim=getMeshDimension();
6132 if(spaceDim!=2 && spaceDim!=3)
6133 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6134 if(meshDim!=2 && meshDim!=3)
6135 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6136 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6138 int nbOfCells=getNumberOfCells();
6139 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6140 arr->alloc(nbOfCells,1);
6141 double *pt=arr->getPointer();
6142 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6143 const int *conn=_nodal_connec->getConstPointer();
6144 const int *connI=_nodal_connec_index->getConstPointer();
6145 const double *coo=_coords->getConstPointer();
6147 for(int i=0;i<nbOfCells;i++,pt++)
6149 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6152 case INTERP_KERNEL::NORM_TRI3:
6154 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6155 *pt=INTERP_KERNEL::triAspectRatio(tmp);
6158 case INTERP_KERNEL::NORM_QUAD4:
6160 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6161 *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6164 case INTERP_KERNEL::NORM_TETRA4:
6166 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6167 *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6171 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6173 conn+=connI[i+1]-connI[i];
6175 ret->setName("AspectRatio");
6176 ret->synchronizeTimeWithSupport();
6181 * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6182 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6183 * treated: INTERP_KERNEL::NORM_QUAD4.
6184 * For a cell of other type an exception is thrown.
6185 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6186 * cells and one time, lying on \a this mesh. The caller is to delete this
6187 * field using decrRef() as it is no more needed.
6188 * \throw If the coordinates array is not set.
6189 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6190 * \throw If the connectivity data array has more than one component.
6191 * \throw If the connectivity data array has a named component.
6192 * \throw If the connectivity index data array has more than one component.
6193 * \throw If the connectivity index data array has a named component.
6194 * \throw If \a this->getMeshDimension() != 2.
6195 * \throw If \a this->getSpaceDimension() != 3.
6196 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6198 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6201 int spaceDim=getSpaceDimension();
6202 int meshDim=getMeshDimension();
6204 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6206 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6207 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6209 int nbOfCells=getNumberOfCells();
6210 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6211 arr->alloc(nbOfCells,1);
6212 double *pt=arr->getPointer();
6213 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6214 const int *conn=_nodal_connec->getConstPointer();
6215 const int *connI=_nodal_connec_index->getConstPointer();
6216 const double *coo=_coords->getConstPointer();
6218 for(int i=0;i<nbOfCells;i++,pt++)
6220 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6223 case INTERP_KERNEL::NORM_QUAD4:
6225 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6226 *pt=INTERP_KERNEL::quadWarp(tmp);
6230 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6232 conn+=connI[i+1]-connI[i];
6234 ret->setName("Warp");
6235 ret->synchronizeTimeWithSupport();
6241 * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6242 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6243 * treated: INTERP_KERNEL::NORM_QUAD4.
6244 * For a cell of other type an exception is thrown.
6245 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6246 * cells and one time, lying on \a this mesh. The caller is to delete this
6247 * field using decrRef() as it is no more needed.
6248 * \throw If the coordinates array is not set.
6249 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6250 * \throw If the connectivity data array has more than one component.
6251 * \throw If the connectivity data array has a named component.
6252 * \throw If the connectivity index data array has more than one component.
6253 * \throw If the connectivity index data array has a named component.
6254 * \throw If \a this->getMeshDimension() != 2.
6255 * \throw If \a this->getSpaceDimension() != 3.
6256 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6258 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6261 int spaceDim=getSpaceDimension();
6262 int meshDim=getMeshDimension();
6264 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6266 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6267 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6269 int nbOfCells=getNumberOfCells();
6270 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6271 arr->alloc(nbOfCells,1);
6272 double *pt=arr->getPointer();
6273 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6274 const int *conn=_nodal_connec->getConstPointer();
6275 const int *connI=_nodal_connec_index->getConstPointer();
6276 const double *coo=_coords->getConstPointer();
6278 for(int i=0;i<nbOfCells;i++,pt++)
6280 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6283 case INTERP_KERNEL::NORM_QUAD4:
6285 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6286 *pt=INTERP_KERNEL::quadSkew(tmp);
6290 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6292 conn+=connI[i+1]-connI[i];
6294 ret->setName("Skew");
6295 ret->synchronizeTimeWithSupport();
6300 * This method aggregate the bbox of each cell and put it into bbox parameter.
6302 * \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)
6303 * For all other cases this input parameter is ignored.
6304 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6306 * \throw If \a this is not fully set (coordinates and connectivity).
6307 * \throw If a cell in \a this has no valid nodeId.
6308 * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6310 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6312 int mDim(getMeshDimension()),sDim(getSpaceDimension());
6313 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.
6314 return getBoundingBoxForBBTreeFast();
6315 if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6317 bool presenceOfQuadratic(false);
6318 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6320 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6321 if(cm.isQuadratic())
6322 presenceOfQuadratic=true;
6324 if(!presenceOfQuadratic)
6325 return getBoundingBoxForBBTreeFast();
6326 if(mDim==2 && sDim==2)
6327 return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6329 return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6331 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) !");
6335 * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6336 * So meshes having quadratic cells the computed bounding boxes can be invalid !
6338 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6340 * \throw If \a this is not fully set (coordinates and connectivity).
6341 * \throw If a cell in \a this has no valid nodeId.
6343 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6345 checkFullyDefined();
6346 int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6347 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6348 double *bbox(ret->getPointer());
6349 for(int i=0;i<nbOfCells*spaceDim;i++)
6351 bbox[2*i]=std::numeric_limits<double>::max();
6352 bbox[2*i+1]=-std::numeric_limits<double>::max();
6354 const double *coordsPtr(_coords->getConstPointer());
6355 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6356 for(int i=0;i<nbOfCells;i++)
6358 int offset=connI[i]+1;
6359 int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6360 for(int j=0;j<nbOfNodesForCell;j++)
6362 int nodeId=conn[offset+j];
6363 if(nodeId>=0 && nodeId<nbOfNodes)
6365 for(int k=0;k<spaceDim;k++)
6367 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6368 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6375 std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6376 throw INTERP_KERNEL::Exception(oss.str().c_str());
6383 * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6384 * useful for 2D meshes having quadratic cells
6385 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6386 * the two extremities of the arc of circle).
6388 * \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)
6389 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6390 * \throw If \a this is not fully defined.
6391 * \throw If \a this is not a mesh with meshDimension equal to 2.
6392 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6393 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6395 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6397 checkFullyDefined();
6398 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6399 if(spaceDim!=2 || mDim!=2)
6400 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!");
6401 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6402 double *bbox(ret->getPointer());
6403 const double *coords(_coords->getConstPointer());
6404 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6405 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6407 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6408 int sz(connI[1]-connI[0]-1);
6409 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6410 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6411 INTERP_KERNEL::QuadraticPolygon *pol(0);
6412 for(int j=0;j<sz;j++)
6414 int nodeId(conn[*connI+1+j]);
6415 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6417 if(!cm.isQuadratic())
6418 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6420 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6421 INTERP_KERNEL::Bounds b; pol->fillBounds(b); delete pol;
6422 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax();
6428 * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6429 * useful for 2D meshes having quadratic cells
6430 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6431 * the two extremities of the arc of circle).
6433 * \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)
6434 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6435 * \throw If \a this is not fully defined.
6436 * \throw If \a this is not a mesh with meshDimension equal to 1.
6437 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6438 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6440 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6442 checkFullyDefined();
6443 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6444 if(spaceDim!=2 || mDim!=1)
6445 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!");
6446 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6447 double *bbox(ret->getPointer());
6448 const double *coords(_coords->getConstPointer());
6449 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6450 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6452 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6453 int sz(connI[1]-connI[0]-1);
6454 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6455 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6456 INTERP_KERNEL::Edge *edge(0);
6457 for(int j=0;j<sz;j++)
6459 int nodeId(conn[*connI+1+j]);
6460 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6462 if(!cm.isQuadratic())
6463 edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6465 edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6466 const INTERP_KERNEL::Bounds& b(edge->getBounds());
6467 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6474 namespace ParaMEDMEMImpl
6479 ConnReader(const int *c, int val):_conn(c),_val(val) { }
6480 bool operator() (const int& pos) { return _conn[pos]!=_val; }
6489 ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6490 bool operator() (const int& pos) { return _conn[pos]==_val; }
6500 * This method expects that \a this is sorted by types. If not an exception will be thrown.
6501 * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6502 * \a this is composed in cell types.
6503 * The returned array is of size 3*n where n is the number of different types present in \a this.
6504 * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here.
6505 * This parameter is kept only for compatibility with other methode listed above.
6507 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6509 checkConnectivityFullyDefined();
6510 const int *conn=_nodal_connec->getConstPointer();
6511 const int *connI=_nodal_connec_index->getConstPointer();
6512 const int *work=connI;
6513 int nbOfCells=getNumberOfCells();
6514 std::size_t n=getAllGeoTypes().size();
6515 std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6516 std::set<INTERP_KERNEL::NormalizedCellType> types;
6517 for(std::size_t i=0;work!=connI+nbOfCells;i++)
6519 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6520 if(types.find(typ)!=types.end())
6522 std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6523 oss << " is not contiguous !";
6524 throw INTERP_KERNEL::Exception(oss.str().c_str());
6528 const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6529 ret[3*i+1]=(int)std::distance(work,work2);
6536 * This method is used to check that this has contiguous cell type in same order than described in \a code.
6537 * only for types cell, type node is not managed.
6538 * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6539 * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6540 * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6541 * If 2 or more same geometric type is in \a code and exception is thrown too.
6543 * This method firstly checks
6544 * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6545 * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6546 * an exception is thrown too.
6548 * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6549 * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown
6550 * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6552 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6555 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6556 std::size_t sz=code.size();
6559 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6560 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6562 bool isNoPflUsed=true;
6563 for(std::size_t i=0;i<n;i++)
6564 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6566 types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6568 if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6569 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6570 isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6573 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6576 if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6577 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6578 if(types.size()==_types.size())
6581 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6583 int *retPtr=ret->getPointer();
6584 const int *connI=_nodal_connec_index->getConstPointer();
6585 const int *conn=_nodal_connec->getConstPointer();
6586 int nbOfCells=getNumberOfCells();
6589 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6591 i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6592 int offset=(int)std::distance(connI,i);
6593 const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6594 int nbOfCellsOfCurType=(int)std::distance(i,j);
6595 if(code[3*kk+2]==-1)
6596 for(int k=0;k<nbOfCellsOfCurType;k++)
6600 int idInIdsPerType=code[3*kk+2];
6601 if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6603 const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6606 zePfl->checkAllocated();
6607 if(zePfl->getNumberOfComponents()==1)
6609 for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6611 if(*k>=0 && *k<nbOfCellsOfCurType)
6612 *retPtr=(*k)+offset;
6615 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6616 oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6617 throw INTERP_KERNEL::Exception(oss.str().c_str());
6622 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6625 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6629 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6630 oss << " should be in [0," << idsPerType.size() << ") !";
6631 throw INTERP_KERNEL::Exception(oss.str().c_str());
6640 * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6641 * 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.
6642 * 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.
6643 * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6645 * \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.
6646 * \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,
6647 * \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6648 * \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.
6649 * This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6650 * \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
6652 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6655 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6656 if(profile->getNumberOfComponents()!=1)
6657 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6658 checkConnectivityFullyDefined();
6659 const int *conn=_nodal_connec->getConstPointer();
6660 const int *connI=_nodal_connec_index->getConstPointer();
6661 int nbOfCells=getNumberOfCells();
6662 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6663 std::vector<int> typeRangeVals(1);
6664 for(const int *i=connI;i!=connI+nbOfCells;)
6666 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6667 if(std::find(types.begin(),types.end(),curType)!=types.end())
6669 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6671 types.push_back(curType);
6672 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6673 typeRangeVals.push_back((int)std::distance(connI,i));
6676 DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6677 profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6678 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6679 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6680 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6682 int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6683 code.resize(3*nbOfCastsFinal);
6684 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6685 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6686 for(int i=0;i<nbOfCastsFinal;i++)
6688 int castId=castsPresent->getIJ(i,0);
6689 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6690 idsInPflPerType2.push_back(tmp3);
6691 code[3*i]=(int)types[castId];
6692 code[3*i+1]=tmp3->getNumberOfTuples();
6693 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6694 if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6696 tmp4->copyStringInfoFrom(*profile);
6697 idsPerType2.push_back(tmp4);
6698 code[3*i+2]=(int)idsPerType2.size()-1;
6705 std::size_t sz2=idsInPflPerType2.size();
6706 idsInPflPerType.resize(sz2);
6707 for(std::size_t i=0;i<sz2;i++)
6709 DataArrayInt *locDa=idsInPflPerType2[i];
6711 idsInPflPerType[i]=locDa;
6713 std::size_t sz=idsPerType2.size();
6714 idsPerType.resize(sz);
6715 for(std::size_t i=0;i<sz;i++)
6717 DataArrayInt *locDa=idsPerType2[i];
6719 idsPerType[i]=locDa;
6724 * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6725 * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6726 * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6727 * 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.
6729 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
6731 checkFullyDefined();
6732 nM1LevMesh->checkFullyDefined();
6733 if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6734 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6735 if(_coords!=nM1LevMesh->getCoords())
6736 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6737 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6738 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6739 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6740 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6741 desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6742 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6743 tmp->setConnectivity(tmp0,tmp1);
6744 tmp->renumberCells(ret0->getConstPointer(),false);
6745 revDesc=tmp->getNodalConnectivity();
6746 revDescIndx=tmp->getNodalConnectivityIndex();
6747 DataArrayInt *ret=0;
6748 if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6751 ret->getMaxValue(tmp2);
6753 std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6754 throw INTERP_KERNEL::Exception(oss.str().c_str());
6759 revDescIndx->incrRef();
6762 meshnM1Old2New=ret0;
6767 * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6768 * necessary for writing the mesh to MED file. Additionally returns a permutation array
6769 * in "Old to New" mode.
6770 * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6771 * this array using decrRef() as it is no more needed.
6772 * \throw If the nodal connectivity of cells is not defined.
6774 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
6776 checkConnectivityFullyDefined();
6777 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6778 renumberCells(ret->getConstPointer(),false);
6783 * This methods checks that cells are sorted by their types.
6784 * This method makes asumption (no check) that connectivity is correctly set before calling.
6786 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6788 checkFullyDefined();
6789 const int *conn=_nodal_connec->getConstPointer();
6790 const int *connI=_nodal_connec_index->getConstPointer();
6791 int nbOfCells=getNumberOfCells();
6792 std::set<INTERP_KERNEL::NormalizedCellType> types;
6793 for(const int *i=connI;i!=connI+nbOfCells;)
6795 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6796 if(types.find(curType)!=types.end())
6798 types.insert(curType);
6799 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6805 * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6806 * The geometric type order is specified by MED file.
6808 * \sa MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6810 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
6812 return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6816 * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6817 * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
6818 * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6819 * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6821 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6823 checkFullyDefined();
6824 const int *conn=_nodal_connec->getConstPointer();
6825 const int *connI=_nodal_connec_index->getConstPointer();
6826 int nbOfCells=getNumberOfCells();
6830 std::set<INTERP_KERNEL::NormalizedCellType> sg;
6831 for(const int *i=connI;i!=connI+nbOfCells;)
6833 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6834 const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6835 if(isTypeExists!=orderEnd)
6837 int pos=(int)std::distance(orderBg,isTypeExists);
6841 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6845 if(sg.find(curType)==sg.end())
6847 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6858 * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6859 * 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
6860 * 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'.
6862 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
6864 checkConnectivityFullyDefined();
6865 int nbOfCells=getNumberOfCells();
6866 const int *conn=_nodal_connec->getConstPointer();
6867 const int *connI=_nodal_connec_index->getConstPointer();
6868 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6869 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6870 tmpa->alloc(nbOfCells,1);
6871 tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6872 tmpb->fillWithZero();
6873 int *tmp=tmpa->getPointer();
6874 int *tmp2=tmpb->getPointer();
6875 for(const int *i=connI;i!=connI+nbOfCells;i++)
6877 const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6880 int pos=(int)std::distance(orderBg,where);
6882 tmp[std::distance(connI,i)]=pos;
6886 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6887 std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6888 oss << " has a type " << cm.getRepr() << " not in input array of type !";
6889 throw INTERP_KERNEL::Exception(oss.str().c_str());
6892 nbPerType=tmpb.retn();
6897 * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
6899 * \return a new object containing the old to new correspondance.
6901 * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6903 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
6905 return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6909 * 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.
6910 * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6911 * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6912 * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6914 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6916 DataArrayInt *nbPerType=0;
6917 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6918 nbPerType->decrRef();
6919 return tmpa->buildPermArrPerLevel();
6923 * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
6924 * The number of cells remains unchanged after the call of this method.
6925 * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6926 * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6928 * \return the array giving the correspondance old to new.
6930 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6932 checkFullyDefined();
6934 const int *conn=_nodal_connec->getConstPointer();
6935 const int *connI=_nodal_connec_index->getConstPointer();
6936 int nbOfCells=getNumberOfCells();
6937 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6938 for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6939 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6941 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6942 types.push_back(curType);
6943 for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6945 DataArrayInt *ret=DataArrayInt::New();
6946 ret->alloc(nbOfCells,1);
6947 int *retPtr=ret->getPointer();
6948 std::fill(retPtr,retPtr+nbOfCells,-1);
6950 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6952 for(const int *i=connI;i!=connI+nbOfCells;i++)
6953 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6954 retPtr[std::distance(connI,i)]=newCellId++;
6956 renumberCells(retPtr,false);
6961 * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
6962 * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
6963 * This method makes asumption that connectivity is correctly set before calling.
6965 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
6967 checkConnectivityFullyDefined();
6968 const int *conn=_nodal_connec->getConstPointer();
6969 const int *connI=_nodal_connec_index->getConstPointer();
6970 int nbOfCells=getNumberOfCells();
6971 std::vector<MEDCouplingUMesh *> ret;
6972 for(const int *i=connI;i!=connI+nbOfCells;)
6974 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6975 int beginCellId=(int)std::distance(connI,i);
6976 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6977 int endCellId=(int)std::distance(connI,i);
6978 int sz=endCellId-beginCellId;
6979 int *cells=new int[sz];
6980 for(int j=0;j<sz;j++)
6981 cells[j]=beginCellId+j;
6982 MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
6990 * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
6991 * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
6992 * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
6994 * \return a newly allocated instance, that the caller must manage.
6995 * \throw If \a this contains more than one geometric type.
6996 * \throw If the nodal connectivity of \a this is not fully defined.
6997 * \throw If the internal data is not coherent.
6999 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7001 checkConnectivityFullyDefined();
7002 if(_types.size()!=1)
7003 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7004 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7005 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7006 ret->setCoords(getCoords());
7007 MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7010 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7011 retC->setNodalConnectivity(c);
7015 MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7017 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7018 DataArrayInt *c=0,*ci=0;
7019 convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7020 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7021 retD->setNodalConnectivity(cs,cis);
7026 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7028 checkConnectivityFullyDefined();
7029 if(_types.size()!=1)
7030 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7031 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7032 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7035 std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7036 oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7037 throw INTERP_KERNEL::Exception(oss.str().c_str());
7039 int nbCells=getNumberOfCells();
7041 int nbNodesPerCell=(int)cm.getNumberOfNodes();
7042 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7043 int *outPtr=connOut->getPointer();
7044 const int *conn=_nodal_connec->begin();
7045 const int *connI=_nodal_connec_index->begin();
7047 for(int i=0;i<nbCells;i++,connI++)
7049 if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7050 outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7053 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 << ") !";
7054 throw INTERP_KERNEL::Exception(oss.str().c_str());
7057 return connOut.retn();
7060 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7062 static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7063 checkConnectivityFullyDefined();
7064 if(_types.size()!=1)
7065 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7066 int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7068 throw INTERP_KERNEL::Exception(msg0);
7069 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7070 c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7071 int *cp(c->getPointer()),*cip(ci->getPointer());
7072 const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7074 for(int i=0;i<nbCells;i++,cip++,incip++)
7076 int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7077 int delta(stop-strt);
7080 if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7081 cp=std::copy(incp+strt,incp+stop,cp);
7083 throw INTERP_KERNEL::Exception(msg0);
7086 throw INTERP_KERNEL::Exception(msg0);
7087 cip[1]=cip[0]+delta;
7089 nodalConn=c.retn(); nodalConnIndex=ci.retn();
7093 * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7094 * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7095 * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7096 * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7097 * are not used here to avoid the build of big permutation array.
7099 * \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
7100 * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7101 * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7102 * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7103 * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7104 * output array gives for each chunck of same type the corresponding mesh id in \b ms.
7105 * \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
7106 * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7108 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7109 DataArrayInt *&szOfCellGrpOfSameType,
7110 DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
7112 std::vector<const MEDCouplingUMesh *> ms2;
7113 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7116 (*it)->checkConnectivityFullyDefined();
7120 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7121 const DataArrayDouble *refCoo=ms2[0]->getCoords();
7122 int meshDim=ms2[0]->getMeshDimension();
7123 std::vector<const MEDCouplingUMesh *> m1ssm;
7124 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7126 std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7127 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7129 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7130 ret1->alloc(0,1); ret2->alloc(0,1);
7131 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7133 if(meshDim!=(*it)->getMeshDimension())
7134 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7135 if(refCoo!=(*it)->getCoords())
7136 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7137 std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7138 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7139 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7140 for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7142 MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7143 m1ssmSingleAuto.push_back(singleCell);
7144 m1ssmSingle.push_back(singleCell);
7145 ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7148 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7149 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7150 std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7151 for(std::size_t i=0;i<m1ssm.size();i++)
7152 m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7153 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7154 szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7155 idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7160 * This method returns a newly created DataArrayInt instance.
7161 * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7163 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7165 checkFullyDefined();
7166 const int *conn=_nodal_connec->getConstPointer();
7167 const int *connIndex=_nodal_connec_index->getConstPointer();
7168 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7169 for(const int *w=begin;w!=end;w++)
7170 if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7171 ret->pushBackSilent(*w);
7176 * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7177 * are in [0:getNumberOfCells())
7179 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7181 checkFullyDefined();
7182 const int *conn=_nodal_connec->getConstPointer();
7183 const int *connI=_nodal_connec_index->getConstPointer();
7184 int nbOfCells=getNumberOfCells();
7185 std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7186 int *tmp=new int[nbOfCells];
7187 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7190 for(const int *i=connI;i!=connI+nbOfCells;i++)
7191 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7192 tmp[std::distance(connI,i)]=j++;
7194 DataArrayInt *ret=DataArrayInt::New();
7195 ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7196 ret->copyStringInfoFrom(*da);
7197 int *retPtr=ret->getPointer();
7198 const int *daPtr=da->getConstPointer();
7199 int nbOfElems=da->getNbOfElems();
7200 for(int k=0;k<nbOfElems;k++)
7201 retPtr[k]=tmp[daPtr[k]];
7207 * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7208 * This method \b works \b for mesh sorted by type.
7209 * cells whose ids is in 'idsPerGeoType' array.
7210 * This method conserves coords and name of mesh.
7212 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7214 std::vector<int> code=getDistributionOfTypes();
7215 std::size_t nOfTypesInThis=code.size()/3;
7216 int sz=0,szOfType=0;
7217 for(std::size_t i=0;i<nOfTypesInThis;i++)
7222 szOfType=code[3*i+1];
7224 for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7225 if(*work<0 || *work>=szOfType)
7227 std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7228 oss << ". It should be in [0," << szOfType << ") !";
7229 throw INTERP_KERNEL::Exception(oss.str().c_str());
7231 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7232 int *idsPtr=idsTokeep->getPointer();
7234 for(std::size_t i=0;i<nOfTypesInThis;i++)
7237 for(int j=0;j<code[3*i+1];j++)
7240 idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7241 offset+=code[3*i+1];
7243 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7244 ret->copyTinyInfoFrom(this);
7249 * This method returns a vector of size 'this->getNumberOfCells()'.
7250 * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7252 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7254 int ncell=getNumberOfCells();
7255 std::vector<bool> ret(ncell);
7256 const int *cI=getNodalConnectivityIndex()->getConstPointer();
7257 const int *c=getNodalConnectivity()->getConstPointer();
7258 for(int i=0;i<ncell;i++)
7260 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7261 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7262 ret[i]=cm.isQuadratic();
7268 * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7270 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7272 if(other->getType()!=UNSTRUCTURED)
7273 throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7274 const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7275 return MergeUMeshes(this,otherC);
7279 * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7280 * computed by averaging coordinates of cell nodes, so this method is not a right
7281 * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7282 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7283 * this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7284 * components. The caller is to delete this array using decrRef() as it is
7286 * \throw If the coordinates array is not set.
7287 * \throw If the nodal connectivity of cells is not defined.
7288 * \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7290 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7292 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7293 int spaceDim=getSpaceDimension();
7294 int nbOfCells=getNumberOfCells();
7295 ret->alloc(nbOfCells,spaceDim);
7296 ret->copyStringInfoFrom(*getCoords());
7297 double *ptToFill=ret->getPointer();
7298 const int *nodal=_nodal_connec->getConstPointer();
7299 const int *nodalI=_nodal_connec_index->getConstPointer();
7300 const double *coor=_coords->getConstPointer();
7301 for(int i=0;i<nbOfCells;i++)
7303 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7304 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7311 * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7312 * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the
7314 * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned
7315 * DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7317 * \sa MEDCouplingUMesh::getBarycenterAndOwner
7318 * \throw If \a this is not fully defined (coordinates and connectivity)
7319 * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7321 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7323 checkFullyDefined();
7324 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7325 int spaceDim=getSpaceDimension();
7326 int nbOfCells=getNumberOfCells();
7327 int nbOfNodes=getNumberOfNodes();
7328 ret->alloc(nbOfCells,spaceDim);
7329 double *ptToFill=ret->getPointer();
7330 const int *nodal=_nodal_connec->getConstPointer();
7331 const int *nodalI=_nodal_connec_index->getConstPointer();
7332 const double *coor=_coords->getConstPointer();
7333 for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7335 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7336 std::fill(ptToFill,ptToFill+spaceDim,0.);
7337 if(type!=INTERP_KERNEL::NORM_POLYHED)
7339 for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7341 if(*conn>=0 && *conn<nbOfNodes)
7342 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7345 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," << nbOfNodes << ") !";
7346 throw INTERP_KERNEL::Exception(oss.str().c_str());
7349 int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7350 if(nbOfNodesInCell>0)
7351 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7354 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7355 throw INTERP_KERNEL::Exception(oss.str().c_str());
7360 std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7362 for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7364 if(*it>=0 && *it<nbOfNodes)
7365 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7368 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," << nbOfNodes << ") !";
7369 throw INTERP_KERNEL::Exception(oss.str().c_str());
7373 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7376 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7377 throw INTERP_KERNEL::Exception(oss.str().c_str());
7385 * Returns a new DataArrayDouble holding barycenters of specified cells. The
7386 * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7387 * are specified via an array of cell ids.
7388 * \warning Validity of the specified cell ids is not checked!
7389 * Valid range is [ 0, \a this->getNumberOfCells() ).
7390 * \param [in] begin - an array of cell ids of interest.
7391 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7392 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7393 * end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7394 * caller is to delete this array using decrRef() as it is no more needed.
7395 * \throw If the coordinates array is not set.
7396 * \throw If the nodal connectivity of cells is not defined.
7398 * \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7399 * \ref py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7401 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7403 DataArrayDouble *ret=DataArrayDouble::New();
7404 int spaceDim=getSpaceDimension();
7405 int nbOfTuple=(int)std::distance(begin,end);
7406 ret->alloc(nbOfTuple,spaceDim);
7407 double *ptToFill=ret->getPointer();
7408 double *tmp=new double[spaceDim];
7409 const int *nodal=_nodal_connec->getConstPointer();
7410 const int *nodalI=_nodal_connec_index->getConstPointer();
7411 const double *coor=_coords->getConstPointer();
7412 for(const int *w=begin;w!=end;w++)
7414 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7415 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7423 * 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".
7424 * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7425 * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7426 * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7427 * This method is useful to detect 2D cells in 3D space that are not coplanar.
7429 * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7430 * \throw If spaceDim!=3 or meshDim!=2.
7431 * \throw If connectivity of \a this is invalid.
7432 * \throw If connectivity of a cell in \a this points to an invalid node.
7434 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7436 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7437 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7438 if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7439 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7440 ret->alloc(nbOfCells,4);
7441 double *retPtr(ret->getPointer());
7442 const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7443 const double *coor(_coords->begin());
7444 for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7446 double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7447 if(nodalI[1]-nodalI[0]>=3)
7449 for(int j=0;j<3;j++)
7451 int nodeId(nodal[nodalI[0]+1+j]);
7452 if(nodeId>=0 && nodeId<nbOfNodes)
7453 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7456 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7457 throw INTERP_KERNEL::Exception(oss.str().c_str());
7463 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7464 throw INTERP_KERNEL::Exception(oss.str().c_str());
7466 INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7467 retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7473 * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7476 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7479 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7480 da->checkAllocated();
7481 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7483 int nbOfTuples=da->getNumberOfTuples();
7484 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7485 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7486 c->alloc(2*nbOfTuples,1);
7487 cI->alloc(nbOfTuples+1,1);
7488 int *cp=c->getPointer();
7489 int *cip=cI->getPointer();
7491 for(int i=0;i<nbOfTuples;i++)
7493 *cp++=INTERP_KERNEL::NORM_POINT1;
7497 ret->setConnectivity(c,cI,true);
7501 * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7502 * Cells and nodes of
7503 * the first mesh precede cells and nodes of the second mesh within the result mesh.
7504 * \param [in] mesh1 - the first mesh.
7505 * \param [in] mesh2 - the second mesh.
7506 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7507 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7508 * is no more needed.
7509 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7510 * \throw If the coordinates array is not set in none of the meshes.
7511 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7512 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7514 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7516 std::vector<const MEDCouplingUMesh *> tmp(2);
7517 tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7518 return MergeUMeshes(tmp);
7522 * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7523 * Cells and nodes of
7524 * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7525 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7526 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7527 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7528 * is no more needed.
7529 * \throw If \a a.size() == 0.
7530 * \throw If \a a[ *i* ] == NULL.
7531 * \throw If the coordinates array is not set in none of the meshes.
7532 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7533 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7535 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7537 std::size_t sz=a.size();
7539 return MergeUMeshesLL(a);
7540 for(std::size_t ii=0;ii<sz;ii++)
7543 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7544 throw INTERP_KERNEL::Exception(oss.str().c_str());
7546 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7547 std::vector< const MEDCouplingUMesh * > aa(sz);
7549 for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7551 const MEDCouplingUMesh *cur=a[i];
7552 const DataArrayDouble *coo=cur->getCoords();
7554 spaceDim=coo->getNumberOfComponents();
7557 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7558 for(std::size_t i=0;i<sz;i++)
7560 bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7563 return MergeUMeshesLL(aa);
7568 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7571 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7572 std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7573 int meshDim=(*it)->getMeshDimension();
7574 int nbOfCells=(*it)->getNumberOfCells();
7575 int meshLgth=(*it++)->getMeshLength();
7576 for(;it!=a.end();it++)
7578 if(meshDim!=(*it)->getMeshDimension())
7579 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7580 nbOfCells+=(*it)->getNumberOfCells();
7581 meshLgth+=(*it)->getMeshLength();
7583 std::vector<const MEDCouplingPointSet *> aps(a.size());
7584 std::copy(a.begin(),a.end(),aps.begin());
7585 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7586 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7587 ret->setCoords(pts);
7588 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7589 c->alloc(meshLgth,1);
7590 int *cPtr=c->getPointer();
7591 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7592 cI->alloc(nbOfCells+1,1);
7593 int *cIPtr=cI->getPointer();
7597 for(it=a.begin();it!=a.end();it++)
7599 int curNbOfCell=(*it)->getNumberOfCells();
7600 const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7601 const int *curC=(*it)->_nodal_connec->getConstPointer();
7602 cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7603 for(int j=0;j<curNbOfCell;j++)
7605 const int *src=curC+curCI[j];
7607 for(;src!=curC+curCI[j+1];src++,cPtr++)
7615 offset+=curCI[curNbOfCell];
7616 offset2+=(*it)->getNumberOfNodes();
7619 ret->setConnectivity(c,cI,true);
7626 * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7627 * dimension and sharing the node coordinates array.
7628 * All cells of the first mesh precede all cells of the second mesh
7629 * within the result mesh.
7630 * \param [in] mesh1 - the first mesh.
7631 * \param [in] mesh2 - the second mesh.
7632 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7633 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7634 * is no more needed.
7635 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7636 * \throw If the meshes do not share the node coordinates array.
7637 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7638 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7640 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7642 std::vector<const MEDCouplingUMesh *> tmp(2);
7643 tmp[0]=mesh1; tmp[1]=mesh2;
7644 return MergeUMeshesOnSameCoords(tmp);
7648 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7649 * dimension and sharing the node coordinates array.
7650 * All cells of the *i*-th mesh precede all cells of the
7651 * (*i*+1)-th mesh within the result mesh.
7652 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7653 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7654 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7655 * is no more needed.
7656 * \throw If \a a.size() == 0.
7657 * \throw If \a a[ *i* ] == NULL.
7658 * \throw If the meshes do not share the node coordinates array.
7659 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7660 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7662 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7665 throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7666 for(std::size_t ii=0;ii<meshes.size();ii++)
7669 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7670 throw INTERP_KERNEL::Exception(oss.str().c_str());
7672 const DataArrayDouble *coords=meshes.front()->getCoords();
7673 int meshDim=meshes.front()->getMeshDimension();
7674 std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7676 int meshIndexLgth=0;
7677 for(;iter!=meshes.end();iter++)
7679 if(coords!=(*iter)->getCoords())
7680 throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7681 if(meshDim!=(*iter)->getMeshDimension())
7682 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7683 meshLgth+=(*iter)->getMeshLength();
7684 meshIndexLgth+=(*iter)->getNumberOfCells();
7686 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7687 nodal->alloc(meshLgth,1);
7688 int *nodalPtr=nodal->getPointer();
7689 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7690 nodalIndex->alloc(meshIndexLgth+1,1);
7691 int *nodalIndexPtr=nodalIndex->getPointer();
7693 for(iter=meshes.begin();iter!=meshes.end();iter++)
7695 const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7696 const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7697 int nbOfCells=(*iter)->getNumberOfCells();
7698 int meshLgth2=(*iter)->getMeshLength();
7699 nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7700 if(iter!=meshes.begin())
7701 nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7703 nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7706 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7707 ret->setName("merge");
7708 ret->setMeshDimension(meshDim);
7709 ret->setConnectivity(nodal,nodalIndex,true);
7710 ret->setCoords(coords);
7715 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7716 * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7717 * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7718 * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7719 * New" mode are returned for each input mesh.
7720 * \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7721 * \param [in] compType - specifies a cell comparison technique. For meaning of its
7722 * valid values [0,1,2], see zipConnectivityTraducer().
7723 * \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7724 * meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7725 * mesh. The caller is to delete each of the arrays using decrRef() as it is
7727 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7728 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7729 * is no more needed.
7730 * \throw If \a meshes.size() == 0.
7731 * \throw If \a meshes[ *i* ] == NULL.
7732 * \throw If the meshes do not share the node coordinates array.
7733 * \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7734 * \throw If the \a meshes are of different dimension (getMeshDimension()).
7735 * \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7736 * \throw If the nodal connectivity any of \a meshes includes an invalid id.
7738 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7740 //All checks are delegated to MergeUMeshesOnSameCoords
7741 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7742 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7743 corr.resize(meshes.size());
7744 std::size_t nbOfMeshes=meshes.size();
7746 const int *o2nPtr=o2n->getConstPointer();
7747 for(std::size_t i=0;i<nbOfMeshes;i++)
7749 DataArrayInt *tmp=DataArrayInt::New();
7750 int curNbOfCells=meshes[i]->getNumberOfCells();
7751 tmp->alloc(curNbOfCells,1);
7752 std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7753 offset+=curNbOfCells;
7754 tmp->setName(meshes[i]->getName());
7761 * Makes all given meshes share the nodal connectivity array. The common connectivity
7762 * array is created by concatenating the connectivity arrays of all given meshes. All
7763 * the given meshes must be of the same space dimension but dimension of cells **can
7764 * differ**. This method is particulary useful in MEDLoader context to build a \ref
7765 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7766 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7767 * \param [in,out] meshes - a vector of meshes to update.
7768 * \throw If any of \a meshes is NULL.
7769 * \throw If the coordinates array is not set in any of \a meshes.
7770 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7771 * \throw If \a meshes are of different space dimension.
7773 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
7775 std::size_t sz=meshes.size();
7778 std::vector< const DataArrayDouble * > coords(meshes.size());
7779 std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7780 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7784 (*it)->checkConnectivityFullyDefined();
7785 const DataArrayDouble *coo=(*it)->getCoords();
7790 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7791 oss << " has no coordinate array defined !";
7792 throw INTERP_KERNEL::Exception(oss.str().c_str());
7797 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7798 oss << " is null !";
7799 throw INTERP_KERNEL::Exception(oss.str().c_str());
7802 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7803 std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7804 int offset=(*it)->getNumberOfNodes();
7805 (*it++)->setCoords(res);
7806 for(;it!=meshes.end();it++)
7808 int oldNumberOfNodes=(*it)->getNumberOfNodes();
7809 (*it)->setCoords(res);
7810 (*it)->shiftNodeNumbersInConn(offset);
7811 offset+=oldNumberOfNodes;
7816 * Merges nodes coincident with a given precision within all given meshes that share
7817 * the nodal connectivity array. The given meshes **can be of different** mesh
7818 * dimension. This method is particulary useful in MEDLoader context to build a \ref
7819 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7820 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7821 * \param [in,out] meshes - a vector of meshes to update.
7822 * \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7823 * \throw If any of \a meshes is NULL.
7824 * \throw If the \a meshes do not share the same node coordinates array.
7825 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7827 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
7831 std::set<const DataArrayDouble *> s;
7832 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7835 s.insert((*it)->getCoords());
7838 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 !";
7839 throw INTERP_KERNEL::Exception(oss.str().c_str());
7844 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 !";
7845 throw INTERP_KERNEL::Exception(oss.str().c_str());
7847 const DataArrayDouble *coo=*(s.begin());
7851 DataArrayInt *comm,*commI;
7852 coo->findCommonTuples(eps,-1,comm,commI);
7853 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7854 int oldNbOfNodes=coo->getNumberOfTuples();
7856 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7857 if(oldNbOfNodes==newNbOfNodes)
7859 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7860 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7862 (*it)->renumberNodesInConn(o2n->getConstPointer());
7863 (*it)->setCoords(newCoords);
7868 * 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.
7869 * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7870 * \param isQuad specifies the policy of connectivity.
7871 * @ret in/out parameter in which the result will be append
7873 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7875 INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7876 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7877 ret.push_back(cm.getExtrudedType());
7878 int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7881 case INTERP_KERNEL::NORM_POINT1:
7883 ret.push_back(connBg[1]);
7884 ret.push_back(connBg[1]+nbOfNodesPerLev);
7887 case INTERP_KERNEL::NORM_SEG2:
7889 int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7890 ret.insert(ret.end(),conn,conn+4);
7893 case INTERP_KERNEL::NORM_SEG3:
7895 int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
7896 ret.insert(ret.end(),conn,conn+8);
7899 case INTERP_KERNEL::NORM_QUAD4:
7901 int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
7902 ret.insert(ret.end(),conn,conn+8);
7905 case INTERP_KERNEL::NORM_TRI3:
7907 int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
7908 ret.insert(ret.end(),conn,conn+6);
7911 case INTERP_KERNEL::NORM_TRI6:
7913 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,
7914 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
7915 ret.insert(ret.end(),conn,conn+15);
7918 case INTERP_KERNEL::NORM_QUAD8:
7921 connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
7922 connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
7923 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
7925 ret.insert(ret.end(),conn,conn+20);
7928 case INTERP_KERNEL::NORM_POLYGON:
7930 std::back_insert_iterator< std::vector<int> > ii(ret);
7931 std::copy(connBg+1,connEnd,ii);
7933 std::reverse_iterator<const int *> rConnBg(connEnd);
7934 std::reverse_iterator<const int *> rConnEnd(connBg+1);
7935 std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
7936 std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
7937 for(std::size_t i=0;i<nbOfRadFaces;i++)
7940 int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
7941 std::copy(conn,conn+4,ii);
7946 throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
7951 * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
7953 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
7956 double v[3]={0.,0.,0.};
7957 std::size_t sz=std::distance(begin,end);
7962 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];
7963 v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
7964 v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
7966 double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
7968 // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
7969 // SEG3 forming a circle):
7970 if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
7972 v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
7973 for(std::size_t j=0;j<sz;j++)
7975 if (j%2) // current point i is quadratic, next point i+1 is standard
7978 ip1 = (j+1)%sz; // ip1 = "i+1"
7980 else // current point i is standard, next point i+1 is quadratic
7985 v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
7986 v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
7987 v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
7989 ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
7995 * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
7997 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
7999 std::vector<std::pair<int,int> > edges;
8000 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8001 const int *bgFace=begin;
8002 for(std::size_t i=0;i<nbOfFaces;i++)
8004 const int *endFace=std::find(bgFace+1,end,-1);
8005 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8006 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8008 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8009 if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8011 edges.push_back(p1);
8015 return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8019 * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8021 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8023 double vec0[3],vec1[3];
8024 std::size_t sz=std::distance(begin,end);
8026 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8027 int nbOfNodes=(int)sz/2;
8028 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8029 const double *pt0=coords+3*begin[0];
8030 const double *pt1=coords+3*begin[nbOfNodes];
8031 vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8032 return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8035 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8037 std::size_t sz=std::distance(begin,end);
8038 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8039 std::size_t nbOfNodes(sz/2);
8040 std::copy(begin,end,(int *)tmp);
8041 for(std::size_t j=1;j<nbOfNodes;j++)
8043 begin[j]=tmp[nbOfNodes-j];
8044 begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8048 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8050 std::size_t sz=std::distance(begin,end);
8052 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8053 double vec0[3],vec1[3];
8054 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8055 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];
8056 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;
8059 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8061 std::size_t sz=std::distance(begin,end);
8063 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8065 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8066 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8067 return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8071 * 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 )
8072 * 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
8075 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8076 * \param [in] coords the coordinates with nb of components exactly equal to 3
8077 * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8078 * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8079 * \param [out] res the result is put at the end of the vector without any alteration of the data.
8081 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8083 int nbFaces=std::count(begin+1,end,-1)+1;
8084 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8085 double *vPtr=v->getPointer();
8086 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8087 double *pPtr=p->getPointer();
8088 const int *stFaceConn=begin+1;
8089 for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8091 const int *endFaceConn=std::find(stFaceConn,end,-1);
8092 ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8093 stFaceConn=endFaceConn+1;
8095 pPtr=p->getPointer(); vPtr=v->getPointer();
8096 DataArrayInt *comm1=0,*commI1=0;
8097 v->findCommonTuples(eps,-1,comm1,commI1);
8098 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8099 const int *comm1Ptr=comm1->getConstPointer();
8100 const int *commI1Ptr=commI1->getConstPointer();
8101 int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8102 res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8104 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8105 mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8106 mm->finishInsertingCells();
8108 for(int i=0;i<nbOfGrps1;i++)
8110 int vecId=comm1Ptr[commI1Ptr[i]];
8111 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8112 DataArrayInt *comm2=0,*commI2=0;
8113 tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8114 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8115 const int *comm2Ptr=comm2->getConstPointer();
8116 const int *commI2Ptr=commI2->getConstPointer();
8117 int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8118 for(int j=0;j<nbOfGrps2;j++)
8120 if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8122 res->insertAtTheEnd(begin,end);
8123 res->pushBackSilent(-1);
8127 int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8128 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8129 ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8130 DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8131 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8132 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8133 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8134 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8135 const int *idsNodePtr=idsNode->getConstPointer();
8136 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];
8137 double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8138 double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8139 if(std::abs(norm)>eps)
8141 double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8142 mm3->rotate(center,vec,angle);
8144 mm3->changeSpaceDimension(2);
8145 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8146 const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8147 const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8148 int nbOfCells=mm4->getNumberOfCells();
8149 for(int k=0;k<nbOfCells;k++)
8152 for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8153 res->pushBackSilent(idsNodePtr[*work]);
8154 res->pushBackSilent(-1);
8159 res->popBackSilent();
8163 * 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
8164 * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8166 * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8167 * \param [in] coords coordinates expected to have 3 components.
8168 * \param [in] begin start of the nodal connectivity of the face.
8169 * \param [in] end end of the nodal connectivity (excluded) of the face.
8170 * \param [out] v the normalized vector of size 3
8171 * \param [out] p the pos of plane
8173 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8175 std::size_t nbPoints=std::distance(begin,end);
8177 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8178 double vec[3]={0.,0.,0.};
8180 bool refFound=false;
8181 for(;j<nbPoints-1 && !refFound;j++)
8183 vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8184 vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8185 vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8186 double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8190 vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8193 for(std::size_t i=j;i<nbPoints-1;i++)
8196 curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8197 curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8198 curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8199 double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8202 curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8203 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];
8204 norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8207 v[0]/=norm; v[1]/=norm; v[2]/=norm;
8208 *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8212 throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8216 * This method tries to obtain a well oriented polyhedron.
8217 * If the algorithm fails, an exception will be thrown.
8219 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8221 std::list< std::pair<int,int> > edgesOK,edgesFinished;
8222 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8223 std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8225 int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8226 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8227 for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8229 while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8232 std::size_t smthChanged=0;
8233 for(std::size_t i=0;i<nbOfFaces;i++)
8235 endFace=std::find(bgFace+1,end,-1);
8236 nbOfEdgesInFace=std::distance(bgFace,endFace);
8240 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8242 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8243 std::pair<int,int> p2(p1.second,p1.first);
8244 bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8245 bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8246 if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8251 std::reverse(bgFace+1,endFace);
8252 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8254 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8255 std::pair<int,int> p2(p1.second,p1.first);
8256 if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8257 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8258 if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8259 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8260 std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8261 if(it!=edgesOK.end())
8264 edgesFinished.push_back(p1);
8267 edgesOK.push_back(p1);
8274 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8276 if(!edgesOK.empty())
8277 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8278 if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8279 {//not lucky ! The first face was not correctly oriented : reorient all faces...
8281 for(std::size_t i=0;i<nbOfFaces;i++)
8283 endFace=std::find(bgFace+1,end,-1);
8284 std::reverse(bgFace+1,endFace);
8290 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8292 int nbOfNodesExpected(skin->getNumberOfNodes());
8293 const int *n2oPtr(n2o->getConstPointer());
8294 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8295 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8296 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8297 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8298 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8299 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8300 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_POLYGON;
8301 if(nbOfNodesExpected<1)
8303 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8304 *work++=n2oPtr[prevNode];
8305 for(int i=1;i<nbOfNodesExpected;i++)
8307 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8309 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8310 conn.erase(prevNode);
8313 int curNode(*(conn.begin()));
8314 *work++=n2oPtr[curNode];
8315 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8316 shar.erase(prevCell);
8319 prevCell=*(shar.begin());
8323 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8326 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8329 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8334 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8336 int nbOfNodesExpected(skin->getNumberOfNodes());
8337 int nbOfTurn(nbOfNodesExpected/2);
8338 const int *n2oPtr(n2o->getConstPointer());
8339 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8340 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8341 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8342 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8343 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8344 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8345 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_QPOLYG;
8346 if(nbOfNodesExpected<1)
8348 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8349 *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8350 for(int i=1;i<nbOfTurn;i++)
8352 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8354 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8355 conn.erase(prevNode);
8358 int curNode(*(conn.begin()));
8359 *work=n2oPtr[curNode];
8360 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8361 shar.erase(prevCell);
8364 int curCell(*(shar.begin()));
8365 work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8371 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8374 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8377 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8383 * This method makes the assumption spacedimension == meshdimension == 2.
8384 * This method works only for linear cells.
8386 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8388 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8390 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8391 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8392 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8393 int oldNbOfNodes(skin->getNumberOfNodes());
8394 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8395 int nbOfNodesExpected(skin->getNumberOfNodes());
8396 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8397 int nbCells(skin->getNumberOfCells());
8398 if(nbCells==nbOfNodesExpected)
8399 return buildUnionOf2DMeshLinear(skin,n2o);
8400 else if(2*nbCells==nbOfNodesExpected)
8401 return buildUnionOf2DMeshQuadratic(skin,n2o);
8403 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8407 * This method makes the assumption spacedimension == meshdimension == 3.
8408 * This method works only for linear cells.
8410 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8412 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8414 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8415 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8416 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8417 const int *conn=m->getNodalConnectivity()->getConstPointer();
8418 const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8419 int nbOfCells=m->getNumberOfCells();
8420 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8421 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED;
8424 work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8425 for(int i=1;i<nbOfCells;i++)
8428 work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8434 * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8435 * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8437 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8441 for(int i=0;i<nbOfNodesInCell;i++)
8442 w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8443 else if(spaceDim==2)
8445 for(int i=0;i<nbOfNodesInCell;i++)
8447 w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8452 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8455 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8457 int nbOfCells=getNumberOfCells();
8459 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8460 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};
8461 ofs << " <" << getVTKDataSetType() << ">\n";
8462 ofs << " <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8463 ofs << " <PointData>\n" << pointData << std::endl;
8464 ofs << " </PointData>\n";
8465 ofs << " <CellData>\n" << cellData << std::endl;
8466 ofs << " </CellData>\n";
8467 ofs << " <Points>\n";
8468 if(getSpaceDimension()==3)
8469 _coords->writeVTK(ofs,8,"Points",byteData);
8472 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8473 coo->writeVTK(ofs,8,"Points",byteData);
8475 ofs << " </Points>\n";
8476 ofs << " <Cells>\n";
8477 const int *cPtr=_nodal_connec->getConstPointer();
8478 const int *cIPtr=_nodal_connec_index->getConstPointer();
8479 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8480 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8481 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8482 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8483 int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8484 int szFaceOffsets=0,szConn=0;
8485 for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8488 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8491 *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8492 w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8496 int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8497 *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8498 std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8499 *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8500 w4=std::copy(c.begin(),c.end(),w4);
8503 types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
8504 types->writeVTK(ofs,8,"UInt8","types",byteData);
8505 offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8506 if(szFaceOffsets!=0)
8507 {//presence of Polyhedra
8508 connectivity->reAlloc(szConn);
8509 faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8510 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8511 w1=faces->getPointer();
8512 for(int i=0;i<nbOfCells;i++)
8513 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8515 int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8517 const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8518 for(int j=0;j<nbFaces;j++)
8520 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8521 *w1++=(int)std::distance(w6,w5);
8522 w1=std::copy(w6,w5,w1);
8526 faces->writeVTK(ofs,8,"Int32","faces",byteData);
8528 connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8529 ofs << " </Cells>\n";
8530 ofs << " </Piece>\n";
8531 ofs << " </" << getVTKDataSetType() << ">\n";
8534 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8536 stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8538 { stream << " Not set !"; return ; }
8539 stream << " Mesh dimension : " << _mesh_dim << ".";
8543 { stream << " No coordinates set !"; return ; }
8544 if(!_coords->isAllocated())
8545 { stream << " Coordinates set but not allocated !"; return ; }
8546 stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8547 stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8548 if(!_nodal_connec_index)
8549 { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8550 if(!_nodal_connec_index->isAllocated())
8551 { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8552 int lgth=_nodal_connec_index->getNumberOfTuples();
8553 int cpt=_nodal_connec_index->getNumberOfComponents();
8554 if(cpt!=1 || lgth<1)
8556 stream << std::endl << "Number of cells : " << lgth-1 << ".";
8559 std::string MEDCouplingUMesh::getVTKDataSetType() const
8561 return std::string("UnstructuredGrid");
8565 * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8566 * returns a result mesh constituted by polygons.
8567 * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8568 * all nodes from m2.
8569 * The meshes should be in 2D space. In
8570 * addition, returns two arrays mapping cells of the result mesh to cells of the input
8572 * \param [in] m1 - the first input mesh which is a partitioned object.
8573 * \param [in] m2 - the second input mesh which is a partition tool.
8574 * \param [in] eps - precision used to detect coincident mesh entities.
8575 * \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8576 * cell an id of the cell of \a m1 it comes from. The caller is to delete
8577 * this array using decrRef() as it is no more needed.
8578 * \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8579 * cell an id of the cell of \a m2 it comes from. -1 value means that a
8580 * result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8581 * any cell of \a m2. The caller is to delete this array using decrRef() as
8582 * it is no more needed.
8583 * \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8584 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8585 * is no more needed.
8586 * \throw If the coordinates array is not set in any of the meshes.
8587 * \throw If the nodal connectivity of cells is not defined in any of the meshes.
8588 * \throw If any of the meshes is not a 2D mesh in 2D space.
8590 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8591 double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8593 m1->checkFullyDefined();
8594 m2->checkFullyDefined();
8595 if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8596 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!");
8598 // Step 1: compute all edge intersections (new nodes)
8599 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8600 MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
8601 DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8602 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
8603 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8604 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8605 IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
8606 m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8607 addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
8608 revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8609 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8610 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8612 // Step 2: re-order newly created nodes according to the ordering found in m2
8613 std::vector< std::vector<int> > intersectEdge2;
8614 BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8615 subDiv2.clear(); dd5=0; dd6=0;
8618 std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8619 std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8620 BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8621 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8623 // Step 4: Prepare final result:
8624 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
8625 addCooDa->alloc((int)(addCoo.size())/2,2);
8626 std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8627 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
8628 addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8629 std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8630 std::vector<const DataArrayDouble *> coordss(4);
8631 coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8632 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
8633 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
8634 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8635 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8636 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8637 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8638 ret->setConnectivity(conn,connI,true);
8639 ret->setCoords(coo);
8640 cellNb1=c1.retn(); cellNb2=c2.retn();
8646 * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
8647 * (newly created) nodes corresponding to the edge intersections.
8649 * @param[out] cr, crI connectivity of the resulting mesh
8650 * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
8651 * TODO: describe input parameters
8653 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8654 const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8655 const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8656 const std::vector<double>& addCoords,
8657 std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8659 static const int SPACEDIM=2;
8660 const double *coo1=m1->getCoords()->getConstPointer();
8661 const int *conn1=m1->getNodalConnectivity()->getConstPointer();
8662 const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
8663 int offset1=m1->getNumberOfNodes();
8664 const double *coo2=m2->getCoords()->getConstPointer();
8665 const int *conn2=m2->getNodalConnectivity()->getConstPointer();
8666 const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
8667 int offset2=offset1+m2->getNumberOfNodes();
8668 int offset3=offset2+((int)addCoords.size())/2;
8669 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
8670 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
8671 // Here a BBTree on 2D-cells, not on segments:
8672 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
8673 int ncell1=m1->getNumberOfCells();
8675 for(int i=0;i<ncell1;i++)
8677 std::vector<int> candidates2;
8678 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
8679 std::map<INTERP_KERNEL::Node *,int> mapp;
8680 std::map<int,INTERP_KERNEL::Node *> mappRev;
8681 INTERP_KERNEL::QuadraticPolygon pol1;
8682 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8683 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8684 // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
8685 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8686 // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
8687 pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8688 desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8690 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
8691 std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8692 INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8693 for(it1.first();!it1.finished();it1.next())
8694 edges1.insert(it1.current()->getPtr());
8696 std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
8697 std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8699 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8701 INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8702 const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8703 // Complete mapping with elements coming from the current cell it2 in mesh2:
8704 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8705 // pol2 is the new QP in the final merged result.
8706 pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8707 pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
8710 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8712 pol1.initLocationsWithOther(pol2s[ii]);
8713 pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8714 //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8715 pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8717 // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
8718 // by m2 but that we still want to keep in the final result.
8723 INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8725 catch(INTERP_KERNEL::Exception& e)
8727 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();
8728 throw INTERP_KERNEL::Exception(oss.str().c_str());
8731 for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8732 (*it).second->decrRef();
8736 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<INTERP_KERNEL::Node *,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
8738 std::map<INTERP_KERNEL::Node *,int>::const_iterator it(m.find(n));
8740 throw INTERP_KERNEL::Exception("Internal error in remapping !");
8741 int v((*it).second);
8742 if(v==forbVal0 || v==forbVal1)
8744 if(std::find(isect.begin(),isect.end(),v)==isect.end())
8748 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<INTERP_KERNEL::Node *,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
8753 bool presenceOfOn(false);
8754 for(int i=0;i<sz;i++)
8756 INTERP_KERNEL::ElementaryEdge *e(c[i]);
8757 if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
8759 IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
8760 IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
8762 return presenceOfOn;
8766 * This method split some of edges of 2D cells in \a this. The edges to be split are specified in \a subNodesInSeg and in \a subNodesInSegI using index storage mode.
8767 * To do the work this method can optionnaly needs information about middle of subedges for quadratic cases if a minimal creation of new nodes is wanted.
8768 * So this method try to reduce at most the number of new nodes. The only case that can lead this method to add nodes if a SEG3 is split without information of middle.
8769 * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to avoid to have a non conform mesh.
8771 * \return int - the number of new nodes created (in most of cases 0).
8773 * \throw If \a this is not coherent.
8774 * \throw If \a this has not spaceDim equal to 2.
8775 * \throw If \a this has not meshDim equal to 2.
8776 * \throw If some subcells needed to be split are orphan.
8777 * \sa MEDCouplingUMesh::conformize2D
8779 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
8781 if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
8782 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
8783 desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
8784 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
8785 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
8786 if(midOpt==0 && midOptI==0)
8788 split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
8791 else if(midOpt!=0 && midOptI!=0)
8792 return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
8794 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
8798 * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
8799 * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
8800 * This method performs a conformization of \b this. So if a edge in \a this can be split into entire edges in \a this this method
8801 * will suppress such edges to use sub edges in \a this. So this method does not add nodes in \a this if merged edges have same nature each other (Linear,Quadratic).
8802 * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
8803 * The modified cells if any are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the
8805 * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
8806 * This method expects that all nodes in \a this are not closer than \a eps.
8807 * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
8809 * \param [in] eps the relative error to detect merged edges.
8810 * \return DataArrayInt * - The list of cellIds in \a this that have been subdivided. If empty, nothing changed in \a this (as if it were a const method). The array is a newly allocated array
8811 * that the user is expected to deal with.
8813 * \throw If \a this is not coherent.
8814 * \throw If \a this has not spaceDim equal to 2.
8815 * \throw If \a this has not meshDim equal to 2.
8816 * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
8818 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
8820 static const int SPACEDIM=2;
8822 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
8823 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
8824 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
8825 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
8826 const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
8827 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
8828 const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
8829 int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
8830 std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
8831 std::vector<double> addCoo;
8832 BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
8833 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8834 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8835 for(int i=0;i<nDescCell;i++)
8837 std::vector<int> candidates;
8838 myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
8839 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
8842 std::map<INTERP_KERNEL::Node *,int> m;
8843 INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
8844 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
8845 INTERP_KERNEL::MergePoints merge;
8846 INTERP_KERNEL::QuadraticPolygon c1,c2;
8847 e1->intersectWith(e2,merge,c1,c2);
8848 e1->decrRef(); e2->decrRef();
8849 if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
8850 overlapEdge[i].push_back(*it);
8851 if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
8852 overlapEdge[*it].push_back(i);
8853 for(std::map<INTERP_KERNEL::Node *,int>::const_iterator it2=m.begin();it2!=m.end();it2++)
8854 (*it2).first->decrRef();
8857 // splitting done. sort intersect point in intersectEdge.
8858 std::vector< std::vector<int> > middle(nDescCell);
8859 int nbOf2DCellsToBeSplit(0);
8860 bool middleNeedsToBeUsed(false);
8861 std::vector<bool> cells2DToTreat(nDescCell,false);
8862 for(int i=0;i<nDescCell;i++)
8864 std::vector<int>& isect(intersectEdge[i]);
8865 int sz((int)isect.size());
8868 std::map<INTERP_KERNEL::Node *,int> m;
8869 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
8870 e->sortSubNodesAbs(coords,isect);
8872 for(std::map<INTERP_KERNEL::Node *,int>::const_iterator it2=m.begin();it2!=m.end();it2++)
8873 (*it2).first->decrRef();
8877 int idx0(rdi[i]),idx1(rdi[i+1]);
8879 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
8880 if(!cells2DToTreat[rd[idx0]])
8882 cells2DToTreat[rd[idx0]]=true;
8883 nbOf2DCellsToBeSplit++;
8885 // try to reuse at most eventual 'middle' of SEG3
8886 std::vector<int>& mid(middle[i]);
8887 mid.resize(sz+1,-1);
8888 if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
8890 middleNeedsToBeUsed=true;
8891 const std::vector<int>& candidates(overlapEdge[i]);
8892 std::vector<int> trueCandidates;
8893 for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
8894 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
8895 trueCandidates.push_back(*itc);
8896 int stNode(c[ci[i]+1]),endNode(isect[0]);
8897 for(int j=0;j<sz+1;j++)
8899 for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
8901 int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
8902 if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
8903 { mid[j]=*itc; break; }
8906 endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
8911 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
8912 if(nbOf2DCellsToBeSplit==0)
8915 int *retPtr(ret->getPointer());
8916 for(int i=0;i<nCell;i++)
8917 if(cells2DToTreat[i])
8920 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
8921 DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
8922 MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
8923 DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
8924 if(middleNeedsToBeUsed)
8925 { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
8926 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
8927 int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
8928 setCoords(modif->getCoords());//if nbOfNodesCreated==0 modif and this have the same coordinates pointer so this line has no effect. But for quadratic cases this line is important.
8929 setPartOfMySelf(ret->begin(),ret->end(),*modif);
8931 bool areNodesMerged; int newNbOfNodes;
8932 if(nbOfNodesCreated!=0)
8933 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
8939 * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
8940 * It builds the descending connectivity of the two meshes, and then using a binary tree
8941 * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
8942 * Documentation about parameters colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
8944 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
8945 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
8946 MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
8947 std::vector<double>& addCoo,
8948 MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
8949 throw(INTERP_KERNEL::Exception)
8951 static const int SPACEDIM=2;
8952 // Build desc connectivity
8953 desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
8954 desc2=DataArrayInt::New();
8955 descIndx2=DataArrayInt::New();
8956 revDesc2=DataArrayInt::New();
8957 revDescIndx2=DataArrayInt::New();
8958 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
8959 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
8960 m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
8961 m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
8962 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
8963 const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
8964 const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
8966 // Build BB tree of all edges in the tool mesh (second mesh)
8967 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
8968 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
8969 int nDescCell1=m1Desc->getNumberOfCells();
8970 int nDescCell2=m2Desc->getNumberOfCells();
8971 intersectEdge1.resize(nDescCell1);
8972 colinear2.resize(nDescCell2);
8973 subDiv2.resize(nDescCell2);
8974 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
8976 std::vector<int> candidates1(1);
8977 int offset1=m1->getNumberOfNodes();
8978 int offset2=offset1+m2->getNumberOfNodes();
8979 for(int i=0;i<nDescCell1;i++) // for all edges in the first mesh
8981 std::vector<int> candidates2; // edges of mesh2 candidate for intersection
8982 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
8983 if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
8985 std::map<INTERP_KERNEL::Node *,int> map1,map2;
8986 // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
8987 INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
8989 INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
8990 // 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
8991 // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
8992 std::set<INTERP_KERNEL::Node *> nodes;
8993 pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
8994 std::size_t szz(nodes.size());
8995 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
8996 std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
8997 for(std::size_t iii=0;iii<szz;iii++,itt++)
8998 { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
8999 // end of protection
9000 // Performs egde cutting:
9001 pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
9006 intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
9008 m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
9009 m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
9013 * This method performs the 2nd step of Partition of 2D mesh.
9014 * This method has 4 inputs :
9015 * - a mesh 'm1' with meshDim==1 and a SpaceDim==2
9016 * - a mesh 'm2' with meshDim==1 and a SpaceDim==2
9017 * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
9018 * 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'
9019 * Nodes end up lying consecutively on a cutted edge.
9020 * \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.
9021 * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
9022 * \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.
9023 * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
9024 * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
9026 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
9027 const std::vector<double>& addCoo,
9028 const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
9030 int offset1=m1->getNumberOfNodes();
9031 int ncell=m2->getNumberOfCells();
9032 const int *c=m2->getNodalConnectivity()->getConstPointer();
9033 const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
9034 const double *coo=m2->getCoords()->getConstPointer();
9035 const double *cooBis=m1->getCoords()->getConstPointer();
9036 int offset2=offset1+m2->getNumberOfNodes();
9037 intersectEdge.resize(ncell);
9038 for(int i=0;i<ncell;i++,cI++)
9040 const std::vector<int>& divs=subDiv[i];
9041 int nnode=cI[1]-cI[0]-1;
9042 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
9043 std::map<INTERP_KERNEL::Node *, int> mapp22;
9044 for(int j=0;j<nnode;j++)
9046 INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
9047 int nnid=c[(*cI)+j+1];
9048 mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
9049 mapp22[nn]=nnid+offset1;
9051 INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
9052 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
9053 ((*it).second.first)->decrRef();
9054 std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
9055 std::map<INTERP_KERNEL::Node *,int> mapp3;
9056 for(std::size_t j=0;j<divs.size();j++)
9059 INTERP_KERNEL::Node *tmp=0;
9061 tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
9063 tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
9065 tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
9069 e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
9070 for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
9077 * 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).
9078 * 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
9079 * with a plane. The result will be put in 'cut3DSuf' out parameter.
9080 * \param [in] cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
9081 * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
9082 * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
9083 * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
9084 * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
9085 * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
9086 * \param [in] desc is the descending connectivity 3DSurf->3DCurve
9087 * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
9088 * \param [out] cut3DSuf input/output param.
9090 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
9091 const int *nodal3DCurve, const int *nodalIndx3DCurve,
9092 const int *desc, const int *descIndx,
9093 std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
9095 std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
9096 int nbOf3DSurfCell=(int)cut3DSurf.size();
9097 for(int i=0;i<nbOf3DSurfCell;i++)
9099 std::vector<int> res;
9100 int offset=descIndx[i];
9101 int nbOfSeg=descIndx[i+1]-offset;
9102 for(int j=0;j<nbOfSeg;j++)
9104 int edgeId=desc[offset+j];
9105 int status=cut3DCurve[edgeId];
9109 res.push_back(status);
9112 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
9113 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
9121 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
9127 std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
9128 std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
9131 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
9135 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
9140 {// case when plane is on a multi colinear edge of a polyhedron
9141 if((int)res.size()==2*nbOfSeg)
9143 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
9146 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
9153 * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
9154 * 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).
9155 * 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
9156 * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
9157 * \param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
9158 * \param desc is the descending connectivity 3D->3DSurf
9159 * \param descIndx is the descending connectivity index 3D->3DSurf
9161 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
9162 const int *desc, const int *descIndx,
9163 DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
9165 checkFullyDefined();
9166 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
9167 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
9168 const int *nodal3D=_nodal_connec->getConstPointer();
9169 const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
9170 int nbOfCells=getNumberOfCells();
9171 for(int i=0;i<nbOfCells;i++)
9173 std::map<int, std::set<int> > m;
9174 int offset=descIndx[i];
9175 int nbOfFaces=descIndx[i+1]-offset;
9178 for(int j=0;j<nbOfFaces;j++)
9180 const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
9181 if(p.first!=-1 && p.second!=-1)
9185 start=p.first; end=p.second;
9186 m[p.first].insert(p.second);
9187 m[p.second].insert(p.first);
9191 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
9192 int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
9193 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
9194 INTERP_KERNEL::NormalizedCellType cmsId;
9195 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
9196 start=tmp[0]; end=tmp[nbOfNodesSon-1];
9197 for(unsigned k=0;k<nbOfNodesSon;k++)
9199 m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
9200 m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
9207 std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
9211 std::map<int, std::set<int> >::const_iterator it=m.find(start);
9212 const std::set<int>& s=(*it).second;
9213 std::set<int> s2; s2.insert(prev);
9215 std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
9218 int val=*s3.begin();
9219 conn.push_back(start);
9226 conn.push_back(end);
9229 nodalRes->insertAtTheEnd(conn.begin(),conn.end());
9230 nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
9231 cellIds->pushBackSilent(i);
9237 * 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
9238 * 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
9239 * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
9240 * 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
9241 * 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.
9243 * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
9245 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
9247 std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
9250 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
9251 if(cm.getDimension()==2)
9253 const int *node=nodalConnBg+1;
9254 int startNode=*node++;
9255 double refX=coords[2*startNode];
9256 for(;node!=nodalConnEnd;node++)
9258 if(coords[2*(*node)]<refX)
9261 refX=coords[2*startNode];
9264 std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
9268 double angle0=-M_PI/2;
9273 double angleNext=0.;
9274 while(nextNode!=startNode)
9278 for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
9280 if(*node!=tmpOut.back() && *node!=prevNode)
9282 tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
9283 double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
9288 res=angle0-angleM+2.*M_PI;
9297 if(nextNode!=startNode)
9299 angle0=angleNext-M_PI;
9302 prevNode=tmpOut.back();
9303 tmpOut.push_back(nextNode);
9306 std::vector<int> tmp3(2*(sz-1));
9307 std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
9308 std::copy(nodalConnBg+1,nodalConnEnd,it);
9309 if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
9311 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
9314 if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
9316 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
9321 nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
9322 nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
9327 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
9330 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
9334 * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
9335 * 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.
9337 * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
9338 * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
9339 * \param [in,out] arr array in which the remove operation will be done.
9340 * \param [in,out] arrIndx array in the remove operation will modify
9341 * \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])
9342 * \return true if \b arr and \b arrIndx have been modified, false if not.
9344 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
9346 if(!arrIndx || !arr)
9347 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
9348 if(offsetForRemoval<0)
9349 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
9350 std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
9351 int nbOfGrps=arrIndx->getNumberOfTuples()-1;
9352 int *arrIPtr=arrIndx->getPointer();
9355 const int *arrPtr=arr->getConstPointer();
9356 std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
9357 for(int i=0;i<nbOfGrps;i++,arrIPtr++)
9359 if(*arrIPtr-previousArrI>offsetForRemoval)
9361 for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
9363 if(s.find(*work)==s.end())
9364 arrOut.push_back(*work);
9367 previousArrI=*arrIPtr;
9368 *arrIPtr=(int)arrOut.size();
9370 if(arr->getNumberOfTuples()==(int)arrOut.size())
9372 arr->alloc((int)arrOut.size(),1);
9373 std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
9378 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9379 * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
9380 * The selection of extraction is done standardly in new2old format.
9381 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
9383 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9384 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9385 * \param [in] arrIn arr origin array from which the extraction will be done.
9386 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9387 * \param [out] arrOut the resulting array
9388 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9389 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
9391 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9392 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9394 if(!arrIn || !arrIndxIn)
9395 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
9396 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
9397 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
9398 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
9399 std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
9400 const int *arrInPtr=arrIn->getConstPointer();
9401 const int *arrIndxPtr=arrIndxIn->getConstPointer();
9402 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
9404 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
9405 int maxSizeOfArr=arrIn->getNumberOfTuples();
9406 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9407 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9408 arrIo->alloc((int)(sz+1),1);
9409 const int *idsIt=idsOfSelectBg;
9410 int *work=arrIo->getPointer();
9413 for(std::size_t i=0;i<sz;i++,work++,idsIt++)
9415 if(*idsIt>=0 && *idsIt<nbOfGrps)
9416 lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
9419 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
9420 throw INTERP_KERNEL::Exception(oss.str().c_str());
9426 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
9427 oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
9428 throw INTERP_KERNEL::Exception(oss.str().c_str());
9431 arro->alloc(lgth,1);
9432 work=arro->getPointer();
9433 idsIt=idsOfSelectBg;
9434 for(std::size_t i=0;i<sz;i++,idsIt++)
9436 if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
9437 work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
9440 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
9441 oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
9442 throw INTERP_KERNEL::Exception(oss.str().c_str());
9446 arrIndexOut=arrIo.retn();
9450 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9451 * 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 ).
9452 * The selection of extraction is done standardly in new2old format.
9453 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
9455 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9456 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9457 * \param [in] arrIn arr origin array from which the extraction will be done.
9458 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9459 * \param [out] arrOut the resulting array
9460 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9461 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
9463 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9464 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9466 if(!arrIn || !arrIndxIn)
9467 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
9468 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
9469 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
9470 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
9471 int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
9472 const int *arrInPtr=arrIn->getConstPointer();
9473 const int *arrIndxPtr=arrIndxIn->getConstPointer();
9474 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
9476 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
9477 int maxSizeOfArr=arrIn->getNumberOfTuples();
9478 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9479 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9480 arrIo->alloc((int)(sz+1),1);
9481 int idsIt=idsOfSelectStart;
9482 int *work=arrIo->getPointer();
9485 for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
9487 if(idsIt>=0 && idsIt<nbOfGrps)
9488 lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
9491 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
9492 throw INTERP_KERNEL::Exception(oss.str().c_str());
9498 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
9499 oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
9500 throw INTERP_KERNEL::Exception(oss.str().c_str());
9503 arro->alloc(lgth,1);
9504 work=arro->getPointer();
9505 idsIt=idsOfSelectStart;
9506 for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
9508 if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
9509 work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
9512 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
9513 oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
9514 throw INTERP_KERNEL::Exception(oss.str().c_str());
9518 arrIndexOut=arrIo.retn();
9522 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9523 * 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
9524 * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9525 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9527 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9528 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9529 * \param [in] arrIn arr origin array from which the extraction will be done.
9530 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9531 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
9532 * \param [in] srcArrIndex index array of \b srcArr
9533 * \param [out] arrOut the resulting array
9534 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9536 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9538 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9539 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9540 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9542 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9543 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
9544 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9545 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9546 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9547 std::vector<bool> v(nbOfTuples,true);
9549 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9550 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9551 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
9553 if(*it>=0 && *it<nbOfTuples)
9556 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
9560 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
9561 throw INTERP_KERNEL::Exception(oss.str().c_str());
9564 srcArrIndexPtr=srcArrIndex->getConstPointer();
9565 arrIo->alloc(nbOfTuples+1,1);
9566 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9567 const int *arrInPtr=arrIn->getConstPointer();
9568 const int *srcArrPtr=srcArr->getConstPointer();
9569 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9570 int *arroPtr=arro->getPointer();
9571 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9575 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9576 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9580 std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
9581 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9582 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9586 arrIndexOut=arrIo.retn();
9590 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9591 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9593 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9594 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9595 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9596 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9597 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
9598 * \param [in] srcArrIndex index array of \b srcArr
9600 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
9602 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9603 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9605 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9606 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
9607 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9608 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9609 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9610 int *arrInOutPtr=arrInOut->getPointer();
9611 const int *srcArrPtr=srcArr->getConstPointer();
9612 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
9614 if(*it>=0 && *it<nbOfTuples)
9616 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
9617 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
9620 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] !";
9621 throw INTERP_KERNEL::Exception(oss.str().c_str());
9626 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
9627 throw INTERP_KERNEL::Exception(oss.str().c_str());
9633 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9634 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9635 * 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]].
9636 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9637 * A negative value in \b arrIn means that it is ignored.
9638 * 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.
9640 * \param [in] arrIn arr origin array from which the extraction will be done.
9641 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9642 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9643 * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
9645 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
9647 int seed=0,nbOfDepthPeelingPerformed=0;
9648 return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
9652 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9653 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9654 * 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]].
9655 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9656 * A negative value in \b arrIn means that it is ignored.
9657 * 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.
9658 * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
9659 * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
9660 * \param [in] arrIn arr origin array from which the extraction will be done.
9661 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9662 * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
9663 * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
9664 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9665 * \sa MEDCouplingUMesh::partitionBySpreadZone
9667 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
9669 nbOfDepthPeelingPerformed=0;
9671 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
9672 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9675 DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
9679 std::vector<bool> fetched(nbOfTuples,false);
9680 return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
9683 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
9685 nbOfDepthPeelingPerformed=0;
9686 if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
9687 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
9688 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9689 std::vector<bool> fetched2(nbOfTuples,false);
9691 for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
9693 if(*seedElt>=0 && *seedElt<nbOfTuples)
9694 { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
9696 { 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()); }
9698 const int *arrInPtr=arrIn->getConstPointer();
9699 const int *arrIndxPtr=arrIndxIn->getConstPointer();
9700 int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
9701 std::vector<int> idsToFetch1(seedBg,seedEnd);
9702 std::vector<int> idsToFetch2;
9703 std::vector<int> *idsToFetch=&idsToFetch1;
9704 std::vector<int> *idsToFetchOther=&idsToFetch2;
9705 while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
9707 for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
9708 for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
9710 { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
9711 std::swap(idsToFetch,idsToFetchOther);
9712 idsToFetchOther->clear();
9713 nbOfDepthPeelingPerformed++;
9715 int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
9717 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
9718 int *retPtr=ret->getPointer();
9719 for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
9726 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9727 * 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
9728 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9729 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9731 * \param [in] start begin of set of ids of the input extraction (included)
9732 * \param [in] end end of set of ids of the input extraction (excluded)
9733 * \param [in] step step of the set of ids in range mode.
9734 * \param [in] arrIn arr origin array from which the extraction will be done.
9735 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9736 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9737 * \param [in] srcArrIndex index array of \b srcArr
9738 * \param [out] arrOut the resulting array
9739 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9741 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
9743 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9744 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9745 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9747 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9748 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
9749 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9750 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9751 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9753 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9754 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9755 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
9757 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9759 if(it>=0 && it<nbOfTuples)
9760 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
9763 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9764 throw INTERP_KERNEL::Exception(oss.str().c_str());
9767 srcArrIndexPtr=srcArrIndex->getConstPointer();
9768 arrIo->alloc(nbOfTuples+1,1);
9769 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9770 const int *arrInPtr=arrIn->getConstPointer();
9771 const int *srcArrPtr=srcArr->getConstPointer();
9772 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9773 int *arroPtr=arro->getPointer();
9774 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9776 int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
9779 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9780 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9784 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9785 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9789 arrIndexOut=arrIo.retn();
9793 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9794 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9796 * \param [in] start begin of set of ids of the input extraction (included)
9797 * \param [in] end end of set of ids of the input extraction (excluded)
9798 * \param [in] step step of the set of ids in range mode.
9799 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9800 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9801 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9802 * \param [in] srcArrIndex index array of \b srcArr
9804 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9806 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9807 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9809 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9810 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
9811 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9812 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9813 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9814 int *arrInOutPtr=arrInOut->getPointer();
9815 const int *srcArrPtr=srcArr->getConstPointer();
9816 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
9818 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9820 if(it>=0 && it<nbOfTuples)
9822 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
9823 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
9826 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9827 throw INTERP_KERNEL::Exception(oss.str().c_str());
9832 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9833 throw INTERP_KERNEL::Exception(oss.str().c_str());
9839 * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
9840 * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
9841 * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
9842 * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
9843 * The sum of measure field of returned mesh is equal to the sum of measure field of this.
9845 * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
9847 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
9849 checkFullyDefined();
9850 int mdim=getMeshDimension();
9851 int spaceDim=getSpaceDimension();
9853 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
9854 std::vector<DataArrayInt *> partition=partitionBySpreadZone();
9855 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
9856 std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
9857 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
9858 ret->setCoords(getCoords());
9859 ret->allocateCells((int)partition.size());
9861 for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
9863 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
9864 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
9868 cell=tmp->buildUnionOf2DMesh();
9871 cell=tmp->buildUnionOf3DMesh();
9874 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
9877 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
9880 ret->finishInsertingCells();
9885 * This method partitions \b this into contiguous zone.
9886 * This method only needs a well defined connectivity. Coordinates are not considered here.
9887 * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
9889 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
9891 int nbOfCellsCur=getNumberOfCells();
9892 std::vector<DataArrayInt *> ret;
9895 DataArrayInt *neigh=0,*neighI=0;
9896 computeNeighborsOfCells(neigh,neighI);
9897 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9898 std::vector<bool> fetchedCells(nbOfCellsCur,false);
9899 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9901 while(seed<nbOfCellsCur)
9903 int nbOfPeelPerformed=0;
9904 ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
9905 seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
9907 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
9908 ret.push_back((*it).retn());
9913 * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
9914 * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
9916 * \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.
9917 * \return a newly allocated DataArrayInt to be managed by the caller.
9918 * \throw In case of \a code has not the right format (typically of size 3*n)
9920 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
9922 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
9923 std::size_t nb=code.size()/3;
9924 if(code.size()%3!=0)
9925 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
9926 ret->alloc((int)nb,2);
9927 int *retPtr=ret->getPointer();
9928 for(std::size_t i=0;i<nb;i++,retPtr+=2)
9930 retPtr[0]=code[3*i+2];
9931 retPtr[1]=code[3*i+2]+code[3*i+1];
9937 * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
9938 * All cells in \a this are expected to be linear 3D cells.
9939 * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
9940 * It leads to an increase to number of cells.
9941 * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
9942 * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints
9943 * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
9945 * \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.
9946 * For all other cells, the splitting policy will be ignored.
9947 * \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.
9948 * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
9949 * an id of old cell producing it. The caller is to delete this array using
9950 * decrRef() as it is no more needed.
9951 * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
9953 * \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
9954 * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
9956 * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
9957 * \throw If \a this is not fully constituted with linear 3D cells.
9958 * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
9960 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
9962 INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
9963 checkConnectivityFullyDefined();
9964 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
9965 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
9966 int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
9967 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
9968 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
9969 int *retPt(ret->getPointer());
9970 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
9971 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
9972 const int *oldc(_nodal_connec->begin());
9973 const int *oldci(_nodal_connec_index->begin());
9974 const double *coords(_coords->begin());
9975 for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
9977 std::vector<int> a; std::vector<double> b;
9978 INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
9979 std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
9980 const int *aa(&a[0]);
9983 for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
9985 *it=(-(*(it))-1+nbNodes);
9986 addPts->insertAtTheEnd(b.begin(),b.end());
9987 nbNodes+=(int)b.size()/3;
9989 for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
9990 newConn->insertAtTheEnd(aa,aa+4);
9992 if(!addPts->empty())
9994 addPts->rearrange(3);
9995 nbOfAdditionalPoints=addPts->getNumberOfTuples();
9996 addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
9997 ret0->setCoords(addPts);
10001 nbOfAdditionalPoints=0;
10002 ret0->setCoords(getCoords());
10004 ret0->setNodalConnectivity(newConn);
10006 ret->computeOffsets2();
10007 n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
10008 return ret0.retn();
10012 * It is the linear part of MEDCouplingUMesh::split2DCells. Here no additionnal nodes will be added in \b this. So coordinates pointer remain unchanged (is not even touch).
10014 * \sa MEDCouplingUMesh::split2DCells
10016 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
10018 checkConnectivityFullyDefined();
10019 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
10020 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
10021 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
10022 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
10023 int prevPosOfCi(ciPtr[0]);
10024 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
10026 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
10027 *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
10028 for(int j=0;j<sz;j++)
10030 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
10031 for(int k=0;k<sz2;k++)
10032 *cPtr++=subPtr[offset2+k];
10034 *cPtr++=oldConn[prevPosOfCi+j+2];
10037 prevPosOfCi=ciPtr[1];
10038 ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
10041 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
10042 _nodal_connec->decrRef();
10043 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
10046 int internalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
10052 int ret(nodesCnter++);
10054 e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
10055 addCoo.insertAtTheEnd(newPt,newPt+2);
10061 * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
10063 * \return int - the number of new nodes created.
10064 * \sa MEDCouplingUMesh::split2DCells
10066 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
10069 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
10070 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
10071 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
10072 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
10073 const int *midPtr(mid->begin()),*midIPtr(midI->begin());
10074 const double *oldCoordsPtr(getCoords()->begin());
10075 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
10076 int prevPosOfCi(ciPtr[0]);
10077 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
10079 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
10080 for(int j=0;j<sz;j++)
10081 { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
10082 *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
10083 for(int j=0;j<sz;j++)//loop over subedges of oldConn
10085 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
10089 cPtr[1]=oldConn[prevPosOfCi+2+j];
10090 cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
10093 std::vector<INTERP_KERNEL::Node *> ns(3);
10094 ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
10095 ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
10096 ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
10097 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
10098 for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
10100 cPtr[1]=subPtr[offset2+k];
10101 cPtr[deltaSz]=internalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
10103 int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
10105 { cPtr[1]=tmpEnd; }
10106 cPtr[deltaSz]=internalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
10108 prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
10109 ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
10112 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
10113 _nodal_connec->decrRef();
10114 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
10115 addCoo->rearrange(2);
10116 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
10118 return addCoo->getNumberOfTuples();
10121 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
10122 _own_cell(true),_cell_id(-1),_nb_cell(0)
10127 _nb_cell=mesh->getNumberOfCells();
10131 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
10139 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
10140 _own_cell(false),_cell_id(bg-1),
10147 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
10150 if(_cell_id<_nb_cell)
10159 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
10165 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
10167 return new MEDCouplingUMeshCellByTypeIterator(_mesh);
10170 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
10176 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
10184 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
10190 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
10195 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
10200 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
10202 return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
10205 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
10210 _nb_cell=mesh->getNumberOfCells();
10214 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
10221 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
10223 const int *c=_mesh->getNodalConnectivity()->getConstPointer();
10224 const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
10225 if(_cell_id<_nb_cell)
10227 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
10228 int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
10229 int startId=_cell_id;
10230 _cell_id+=nbOfElems;
10231 return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
10237 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
10241 _conn=mesh->getNodalConnectivity()->getPointer();
10242 _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
10246 void MEDCouplingUMeshCell::next()
10248 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
10253 _conn_lgth=_conn_indx[1]-_conn_indx[0];
10256 std::string MEDCouplingUMeshCell::repr() const
10258 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
10260 std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
10262 std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
10266 return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
10269 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
10271 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
10272 return (INTERP_KERNEL::NormalizedCellType)_conn[0];
10274 return INTERP_KERNEL::NORM_ERROR;
10277 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
10280 if(_conn_lgth!=NOTICABLE_FIRST_VAL)