1 // Copyright (C) 2007-2013 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.
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 "InterpKernelMeshQuality.hxx"
34 #include "InterpKernelCellSimplify.hxx"
35 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
36 #include "MEDCouplingAutoRefCountObjectPtr.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 char *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);
92 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other) throw(INTERP_KERNEL::Exception)
95 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
96 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
98 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
99 MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
100 setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
103 std::size_t MEDCouplingUMesh::getHeapMemorySize() const
107 ret+=_nodal_connec->getHeapMemorySize();
108 if(_nodal_connec_index)
109 ret+=_nodal_connec_index->getHeapMemorySize();
110 return MEDCouplingPointSet::getHeapMemorySize()+ret;
113 void MEDCouplingUMesh::updateTime() const
115 MEDCouplingPointSet::updateTime();
118 updateTimeWith(*_nodal_connec);
120 if(_nodal_connec_index)
122 updateTimeWith(*_nodal_connec_index);
126 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
131 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
132 * then \a this mesh is most probably is writable, exchangeable and available for most
133 * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
134 * this method to check that all is in order with \a this mesh.
135 * \throw If the mesh dimension is not set.
136 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
137 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
138 * \throw If the connectivity data array has more than one component.
139 * \throw If the connectivity data array has a named component.
140 * \throw If the connectivity index data array has more than one component.
141 * \throw If the connectivity index data array has a named component.
143 void MEDCouplingUMesh::checkCoherency() const throw(INTERP_KERNEL::Exception)
146 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
148 MEDCouplingPointSet::checkCoherency();
149 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
151 if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
153 std::ostringstream message;
154 message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
155 throw INTERP_KERNEL::Exception(message.str().c_str());
160 if(_nodal_connec->getNumberOfComponents()!=1)
161 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
162 if(_nodal_connec->getInfoOnComponent(0)!="")
163 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
167 throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
168 if(_nodal_connec_index)
170 if(_nodal_connec_index->getNumberOfComponents()!=1)
171 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
172 if(_nodal_connec_index->getInfoOnComponent(0)!="")
173 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
177 throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
181 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
182 * then \a this mesh is most probably is writable, exchangeable and available for all
183 * algorithms. <br> In addition to the checks performed by checkCoherency(), this
184 * method thoroughly checks the nodal connectivity.
185 * \param [in] eps - a not used parameter.
186 * \throw If the mesh dimension is not set.
187 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
188 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
189 * \throw If the connectivity data array has more than one component.
190 * \throw If the connectivity data array has a named component.
191 * \throw If the connectivity index data array has more than one component.
192 * \throw If the connectivity index data array has a named component.
193 * \throw If number of nodes defining an element does not correspond to the type of element.
194 * \throw If the nodal connectivity includes an invalid node id.
196 void MEDCouplingUMesh::checkCoherency1(double eps) const throw(INTERP_KERNEL::Exception)
201 int meshDim=getMeshDimension();
202 int nbOfNodes=getNumberOfNodes();
203 int nbOfCells=getNumberOfCells();
204 const int *ptr=_nodal_connec->getConstPointer();
205 const int *ptrI=_nodal_connec_index->getConstPointer();
206 for(int i=0;i<nbOfCells;i++)
208 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
209 if((int)cm.getDimension()!=meshDim)
211 std::ostringstream oss;
212 oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
213 throw INTERP_KERNEL::Exception(oss.str().c_str());
215 int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
217 if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
219 std::ostringstream oss;
220 oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " << cm.getNumberOfNodes();
221 oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
222 throw INTERP_KERNEL::Exception(oss.str().c_str());
224 for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
229 if(nodeId>=nbOfNodes)
231 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes !";
232 throw INTERP_KERNEL::Exception(oss.str().c_str());
237 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " in connectivity ! sounds bad !";
238 throw INTERP_KERNEL::Exception(oss.str().c_str());
242 if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
244 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #-1 in connectivity ! sounds bad !";
245 throw INTERP_KERNEL::Exception(oss.str().c_str());
254 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
255 * then \a this mesh is most probably is writable, exchangeable and available for all
256 * algorithms. <br> This method performs the same checks as checkCoherency1() does.
257 * \param [in] eps - a not used parameter.
258 * \throw If the mesh dimension is not set.
259 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
260 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
261 * \throw If the connectivity data array has more than one component.
262 * \throw If the connectivity data array has a named component.
263 * \throw If the connectivity index data array has more than one component.
264 * \throw If the connectivity index data array has a named component.
265 * \throw If number of nodes defining an element does not correspond to the type of element.
266 * \throw If the nodal connectivity includes an invalid node id.
268 void MEDCouplingUMesh::checkCoherency2(double eps) const throw(INTERP_KERNEL::Exception)
270 checkCoherency1(eps);
274 * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
275 * elements contained in the mesh. For more info on the mesh dimension see
276 * \ref MEDCouplingUMeshPage.
277 * \param [in] meshDim - a new mesh dimension.
278 * \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
280 void MEDCouplingUMesh::setMeshDimension(int meshDim)
282 if(meshDim<-1 || meshDim>3)
283 throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
289 * Allocates memory to store an estimation of the given number of cells. Closer is the estimation to the number of cells effectively inserted,
290 * less will be the needs to realloc. If the number of cells to be inserted is not known simply put 0 to this parameter.
291 * If a nodal connectivity previouly existed before the call of this method, it will be reset.
293 * \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
295 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
296 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
298 void MEDCouplingUMesh::allocateCells(int nbOfCells)
301 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
302 if(_nodal_connec_index)
304 _nodal_connec_index->decrRef();
308 _nodal_connec->decrRef();
310 _nodal_connec_index=DataArrayInt::New();
311 _nodal_connec_index->reserve(nbOfCells+1);
312 _nodal_connec_index->pushBackSilent(0);
313 _nodal_connec=DataArrayInt::New();
314 _nodal_connec->reserve(2*nbOfCells);
320 * Appends a cell to the connectivity array. For deeper understanding what is
321 * happening see \ref MEDCouplingUMeshNodalConnectivity.
322 * \param [in] type - type of cell to add.
323 * \param [in] size - number of nodes constituting this cell.
324 * \param [in] nodalConnOfCell - the connectivity of the cell to add.
326 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
327 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
329 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell) throw(INTERP_KERNEL::Exception)
331 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
332 if(_nodal_connec_index==0)
333 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
334 if((int)cm.getDimension()==_mesh_dim)
337 if(size!=(int)cm.getNumberOfNodes())
339 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
340 oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
341 throw INTERP_KERNEL::Exception(oss.str().c_str());
343 int idx=_nodal_connec_index->back();
345 _nodal_connec_index->pushBackSilent(val);
346 _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
351 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
352 oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
353 oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
354 throw INTERP_KERNEL::Exception(oss.str().c_str());
359 * Compacts data arrays to release unused memory. This method is to be called after
360 * finishing cell insertion using \a this->insertNextCell().
362 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
363 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
365 void MEDCouplingUMesh::finishInsertingCells()
367 _nodal_connec->pack();
368 _nodal_connec_index->pack();
369 _nodal_connec->declareAsNew();
370 _nodal_connec_index->declareAsNew();
375 * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
376 * Useful for python users.
378 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
380 return new MEDCouplingUMeshCellIterator(this);
384 * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
385 * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
386 * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
387 * Useful for python users.
389 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType() throw(INTERP_KERNEL::Exception)
391 if(!checkConsecutiveCellTypes())
392 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
393 return new MEDCouplingUMeshCellByTypeEntry(this);
397 * Returns a set of all cell types available in \a this mesh.
398 * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
399 * \warning this method does not throw any exception even if \a this is not defined.
401 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
407 * This method is a method that compares \a this and \a other.
408 * This method compares \b all attributes, even names and component names.
410 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const throw(INTERP_KERNEL::Exception)
413 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
414 std::ostringstream oss; oss.precision(15);
415 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
418 reason="mesh given in input is not castable in MEDCouplingUMesh !";
421 if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
423 if(_mesh_dim!=otherC->_mesh_dim)
425 oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" << otherC->_mesh_dim;
429 if(_types!=otherC->_types)
431 oss << "umesh geometric type mismatch :\nThis geometric types are :";
432 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
433 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
434 oss << "\nOther geometric types are :";
435 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
436 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
440 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
441 if(_nodal_connec==0 || otherC->_nodal_connec==0)
443 reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
446 if(_nodal_connec!=otherC->_nodal_connec)
447 if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
449 reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
452 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
453 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
455 reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
458 if(_nodal_connec_index!=otherC->_nodal_connec_index)
459 if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
461 reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
468 * Checks if data arrays of this mesh (node coordinates, nodal
469 * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
471 * \param [in] other - the mesh to compare with.
472 * \param [in] prec - precision value used to compare node coordinates.
473 * \return bool - \a true if the two meshes are same.
475 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
477 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
480 if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
482 if(_mesh_dim!=otherC->_mesh_dim)
484 if(_types!=otherC->_types)
486 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
487 if(_nodal_connec==0 || otherC->_nodal_connec==0)
489 if(_nodal_connec!=otherC->_nodal_connec)
490 if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
492 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
493 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
495 if(_nodal_connec_index!=otherC->_nodal_connec_index)
496 if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
502 * Checks if \a this and \a other meshes are geometrically equivalent with high
503 * probability, else an exception is thrown. The meshes are considered equivalent if
504 * (1) meshes contain the same number of nodes and the same number of elements of the
505 * same types (2) three cells of the two meshes (first, last and middle) are based
506 * on coincident nodes (with a specified precision).
507 * \param [in] other - the mesh to compare with.
508 * \param [in] prec - the precision used to compare nodes of the two meshes.
509 * \throw If the two meshes do not match.
511 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const throw(INTERP_KERNEL::Exception)
513 MEDCouplingPointSet::checkFastEquivalWith(other,prec);
514 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
516 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !");
520 * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
521 * cells each node belongs to.
522 * \warning For speed reasons, this method does not check if node ids in the nodal
523 * connectivity correspond to the size of node coordinates array.
524 * \param [in,out] revNodal - an array holding ids of cells sharing each node.
525 * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
526 * dividing cell ids in \a revNodal into groups each referring to one
527 * node. Its every element (except the last one) is an index pointing to the
528 * first id of a group of cells. For example cells sharing the node #1 are
529 * described by following range of indices:
530 * [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
531 * \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
532 * Number of cells sharing the *i*-th node is
533 * \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
534 * \throw If the coordinates array is not set.
535 * \throw If the nodal connectivity of cells is not defined.
537 * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
538 * \ref py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
540 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const throw(INTERP_KERNEL::Exception)
543 int nbOfNodes=getNumberOfNodes();
544 int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
545 revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
546 std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
547 const int *conn=_nodal_connec->getConstPointer();
548 const int *connIndex=_nodal_connec_index->getConstPointer();
549 int nbOfCells=getNumberOfCells();
550 int nbOfEltsInRevNodal=0;
551 for(int eltId=0;eltId<nbOfCells;eltId++)
553 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
554 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
555 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
556 if(*iter>=0)//for polyhedrons
558 nbOfEltsInRevNodal++;
559 revNodalIndxPtr[(*iter)+1]++;
562 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
563 int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
564 revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
565 std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
566 for(int eltId=0;eltId<nbOfCells;eltId++)
568 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
569 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
570 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
571 if(*iter>=0)//for polyhedrons
572 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
578 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
583 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
589 if(cm.getOrientationStatus(nb,conn1,conn2))
596 class MinusOneSonsGenerator
599 MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
600 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
601 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
602 static const int DELTA=1;
604 const INTERP_KERNEL::CellModel& _cm;
607 class MinusOneSonsGeneratorBiQuadratic
610 MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
611 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
612 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
613 static const int DELTA=1;
615 const INTERP_KERNEL::CellModel& _cm;
618 class MinusTwoSonsGenerator
621 MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
622 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
623 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
624 static const int DELTA=2;
626 const INTERP_KERNEL::CellModel& _cm;
632 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
633 * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
634 * describing correspondence between cells of \a this and the result meshes are
635 * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
636 * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
637 * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
638 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
639 * \warning For speed reasons, this method does not check if node ids in the nodal
640 * connectivity correspond to the size of node coordinates array.
641 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
642 * to write this mesh to the MED file, its cells must be sorted using
643 * sortCellsInMEDFileFrmt().
644 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
645 * each cell of \a this mesh.
646 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
647 * dividing cell ids in \a desc into groups each referring to one
648 * cell of \a this mesh. Its every element (except the last one) is an index
649 * pointing to the first id of a group of cells. For example cells of the
650 * result mesh bounding the cell #1 of \a this mesh are described by following
652 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
653 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
654 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
655 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
656 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
657 * by each cell of the result mesh.
658 * \param [in,out] revDescIndx - the array, of length one more than number of cells
659 * in the result mesh,
660 * dividing cell ids in \a revDesc into groups each referring to one
661 * cell of the result mesh the same way as \a descIndx divides \a desc.
662 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
663 * delete this mesh using decrRef() as it is no more needed.
664 * \throw If the coordinates array is not set.
665 * \throw If the nodal connectivity of cells is node defined.
666 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
667 * revDescIndx == NULL.
669 * \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
670 * \ref py_mcumesh_buildDescendingConnectivity "Here is a Python example".
671 * \sa buildDescendingConnectivity2()
673 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
675 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
679 * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
680 * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
681 * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
682 * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
683 * \sa MEDCouplingUMesh::buildDescendingConnectivity
685 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
688 if(getMeshDimension()!=3)
689 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
690 return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
694 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
695 * this->getMeshDimension(), that bound cells of \a this mesh. In
696 * addition arrays describing correspondence between cells of \a this and the result
697 * meshes are returned. The arrays \a desc and \a descIndx describe the descending
698 * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
699 * mesh. This method differs from buildDescendingConnectivity() in that apart
700 * from cell ids, \a desc returns mutual orientation of cells in \a this and the
701 * result meshes. So a positive id means that order of nodes in corresponding cells
702 * of two meshes is same, and a negative id means a reverse order of nodes. Since a
703 * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
704 * i.e. cell ids are one-based.
705 * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
706 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
707 * \warning For speed reasons, this method does not check if node ids in the nodal
708 * connectivity correspond to the size of node coordinates array.
709 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
710 * to write this mesh to the MED file, its cells must be sorted using
711 * sortCellsInMEDFileFrmt().
712 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
713 * each cell of \a this mesh.
714 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
715 * dividing cell ids in \a desc into groups each referring to one
716 * cell of \a this mesh. Its every element (except the last one) is an index
717 * pointing to the first id of a group of cells. For example cells of the
718 * result mesh bounding the cell #1 of \a this mesh are described by following
720 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
721 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
722 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
723 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
724 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
725 * by each cell of the result mesh.
726 * \param [in,out] revDescIndx - the array, of length one more than number of cells
727 * in the result mesh,
728 * dividing cell ids in \a revDesc into groups each referring to one
729 * cell of the result mesh the same way as \a descIndx divides \a desc.
730 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
731 * shares the node coordinates array with \a this mesh. The caller is to
732 * delete this mesh using decrRef() as it is no more needed.
733 * \throw If the coordinates array is not set.
734 * \throw If the nodal connectivity of cells is node defined.
735 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
736 * revDescIndx == NULL.
738 * \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
739 * \ref py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
740 * \sa buildDescendingConnectivity()
742 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
744 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
748 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
749 * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
750 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
751 * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
753 * \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
754 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
755 * \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.
757 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const throw(INTERP_KERNEL::Exception)
759 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
760 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
761 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
762 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
763 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
765 ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
769 * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
770 * 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,
771 * excluding a set of meshdim-1 cells in input descending connectivity.
772 * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
773 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
774 * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
776 * \param [in] desc descending connectivity array.
777 * \param [in] descIndx descending connectivity index array used to walk through \b desc.
778 * \param [in] revDesc reverse descending connectivity array.
779 * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
780 * \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
781 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
782 * \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.
784 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
785 DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) throw(INTERP_KERNEL::Exception)
787 if(!desc || !descIndx || !revDesc || !revDescIndx)
788 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
789 const int *descPtr=desc->getConstPointer();
790 const int *descIPtr=descIndx->getConstPointer();
791 const int *revDescPtr=revDesc->getConstPointer();
792 const int *revDescIPtr=revDescIndx->getConstPointer();
794 int nbCells=descIndx->getNumberOfTuples()-1;
795 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
796 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
797 int *out1Ptr=out1->getPointer();
799 out0->reserve(desc->getNumberOfTuples());
800 for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
802 for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
804 std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
806 out0->insertAtTheEnd(s.begin(),s.end());
808 *out1Ptr=out0->getNumberOfTuples();
810 neighbors=out0.retn();
811 neighborsIndx=out1.retn();
817 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
818 * For speed reasons no check of this will be done.
820 template<class SonsGenerator>
821 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const throw(INTERP_KERNEL::Exception)
823 if(!desc || !descIndx || !revDesc || !revDescIndx)
824 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
825 checkConnectivityFullyDefined();
826 int nbOfCells=getNumberOfCells();
827 int nbOfNodes=getNumberOfNodes();
828 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
829 int *revNodalIndxPtr=revNodalIndx->getPointer();
830 const int *conn=_nodal_connec->getConstPointer();
831 const int *connIndex=_nodal_connec_index->getConstPointer();
832 std::string name="Mesh constituent of "; name+=getName();
833 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name.c_str(),getMeshDimension()-SonsGenerator::DELTA);
834 ret->setCoords(getCoords());
835 ret->allocateCells(2*nbOfCells);
836 descIndx->alloc(nbOfCells+1,1);
837 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
838 int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
839 for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
841 int pos=connIndex[eltId];
842 int posP1=connIndex[eltId+1];
843 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
844 SonsGenerator sg(cm);
845 unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
846 INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
847 for(unsigned i=0;i<nbOfSons;i++)
849 INTERP_KERNEL::NormalizedCellType cmsId;
850 unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
851 for(unsigned k=0;k<nbOfNodesSon;k++)
853 revNodalIndxPtr[tmp[k]+1]++;
854 ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
855 revDesc2->pushBackSilent(eltId);
857 descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
859 int nbOfCellsM1=ret->getNumberOfCells();
860 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
861 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
862 std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
863 int *revNodalPtr=revNodal->getPointer();
864 const int *connM1=ret->getNodalConnectivity()->getConstPointer();
865 const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
866 for(int eltId=0;eltId<nbOfCellsM1;eltId++)
868 const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
869 const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
870 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
871 if(*iter>=0)//for polyhedrons
872 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
875 DataArrayInt *commonCells=0,*commonCellsI=0;
876 FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
877 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
878 const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
879 int newNbOfCellsM1=-1;
880 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
881 commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
882 std::vector<bool> isImpacted(nbOfCellsM1,false);
883 for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
884 for(int work2=work[0];work2!=work[1];work2++)
885 isImpacted[commonCellsPtr[work2]]=true;
886 const int *o2nM1Ptr=o2nM1->getConstPointer();
887 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
888 const int *n2oM1Ptr=n2oM1->getConstPointer();
889 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
890 ret2->copyTinyInfoFrom(this);
891 desc->alloc(descIndx->back(),1);
892 int *descPtr=desc->getPointer();
893 const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
894 for(int i=0;i<nbOfCellsM1;i++,descPtr++)
897 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
900 if(i!=n2oM1Ptr[o2nM1Ptr[i]])
902 const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
903 *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
906 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
909 revDesc->reserve(newNbOfCellsM1);
910 revDescIndx->alloc(newNbOfCellsM1+1,1);
911 int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
912 const int *revDesc2Ptr=revDesc2->getConstPointer();
913 for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
915 int oldCellIdM1=n2oM1Ptr[i];
916 if(!isImpacted[oldCellIdM1])
918 revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
919 revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
923 for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
924 revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
925 revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
933 struct MEDCouplingAccVisit
935 MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
936 int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
937 int _new_nb_of_nodes;
943 * Converts specified cells to either polygons (if \a this is a 2D mesh) or
944 * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
945 * array of cell ids. Pay attention that after conversion all algorithms work slower
946 * with \a this mesh than before conversion. <br> If an exception is thrown during the
947 * conversion due presence of invalid ids in the array of cells to convert, as a
948 * result \a this mesh contains some already converted elements. In this case the 2D
949 * mesh remains valid but 3D mesh becomes \b inconsistent!
950 * \warning This method can significantly modify the order of geometric types in \a this,
951 * hence, to write this mesh to the MED file, its cells must be sorted using
952 * sortCellsInMEDFileFrmt().
953 * \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
954 * \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
955 * cellIdsToConvertBg.
956 * \throw If the coordinates array is not set.
957 * \throw If the nodal connectivity of cells is node defined.
958 * \throw If dimension of \a this mesh is not either 2 or 3.
960 * \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
961 * \ref py_mcumesh_convertToPolyTypes "Here is a Python example".
963 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
966 int dim=getMeshDimension();
968 throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
969 int nbOfCells=getNumberOfCells();
972 const int *connIndex=_nodal_connec_index->getConstPointer();
973 int *conn=_nodal_connec->getPointer();
974 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
976 if(*iter>=0 && *iter<nbOfCells)
978 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
979 if(!cm.isQuadratic())
980 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
982 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
986 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
987 oss << " in range [0," << nbOfCells << ") !";
988 throw INTERP_KERNEL::Exception(oss.str().c_str());
994 int *connIndex=_nodal_connec_index->getPointer();
995 int connIndexLgth=_nodal_connec_index->getNbOfElems();
996 const int *connOld=_nodal_connec->getConstPointer();
997 int connOldLgth=_nodal_connec->getNbOfElems();
998 std::vector<int> connNew(connOld,connOld+connOldLgth);
999 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1001 if(*iter>=0 && *iter<nbOfCells)
1003 int pos=connIndex[*iter];
1004 int posP1=connIndex[(*iter)+1];
1005 int lgthOld=posP1-pos-1;
1006 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connNew[pos]);
1007 connNew[pos]=INTERP_KERNEL::NORM_POLYHED;
1008 unsigned nbOfFaces=cm.getNumberOfSons2(&connNew[pos+1],lgthOld);
1009 int *tmp=new int[nbOfFaces*lgthOld];
1011 for(int j=0;j<(int)nbOfFaces;j++)
1013 INTERP_KERNEL::NormalizedCellType type;
1014 unsigned offset=cm.fillSonCellNodalConnectivity2(j,&connNew[pos+1],lgthOld,work,type);
1018 std::size_t newLgth=std::distance(tmp,work)-1;
1019 std::size_t delta=newLgth-lgthOld;
1020 std::transform(connIndex+(*iter)+1,connIndex+connIndexLgth,connIndex+(*iter)+1,std::bind2nd(std::plus<int>(),delta));
1021 connNew.insert(connNew.begin()+posP1,tmp+lgthOld,tmp+newLgth);
1022 std::copy(tmp,tmp+lgthOld,connNew.begin()+pos+1);
1027 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1028 oss << " in range [0," << nbOfCells << ") !";
1029 throw INTERP_KERNEL::Exception(oss.str().c_str());
1032 _nodal_connec->alloc((int)connNew.size(),1);
1033 int *newConnPtr=_nodal_connec->getPointer();
1034 std::copy(connNew.begin(),connNew.end(),newConnPtr);
1040 * Converts all cells to either polygons (if \a this is a 2D mesh) or
1041 * polyhedrons (if \a this is a 3D mesh).
1042 * \warning As this method is purely for user-friendliness and no optimization is
1043 * done to avoid construction of a useless vector, this method can be costly
1045 * \throw If the coordinates array is not set.
1046 * \throw If the nodal connectivity of cells is node defined.
1047 * \throw If dimension of \a this mesh is not either 2 or 3.
1049 void MEDCouplingUMesh::convertAllToPoly()
1051 int nbOfCells=getNumberOfCells();
1052 std::vector<int> cellIds(nbOfCells);
1053 for(int i=0;i<nbOfCells;i++)
1055 convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1059 * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1060 * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1061 * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1062 * base facet of the volume and the second half of nodes describes an opposite facet
1063 * having the same number of nodes as the base one. This method converts such
1064 * connectivity to a valid polyhedral format where connectivity of each facet is
1065 * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1066 * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1067 * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1068 * a correct orientation of the first facet of a polyhedron, else orientation of a
1069 * corrected cell is reverse.<br>
1070 * This method is useful to build an extruded unstructured mesh with polyhedrons as
1071 * it releases the user from boring description of polyhedra connectivity in the valid
1073 * \throw If \a this->getMeshDimension() != 3.
1074 * \throw If \a this->getSpaceDimension() != 3.
1075 * \throw If the nodal connectivity of cells is not defined.
1076 * \throw If the coordinates array is not set.
1077 * \throw If \a this mesh contains polyhedrons with the valid connectivity.
1078 * \throw If \a this mesh contains polyhedrons with odd number of nodes.
1080 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1081 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1083 void MEDCouplingUMesh::convertExtrudedPolyhedra() throw(INTERP_KERNEL::Exception)
1085 checkFullyDefined();
1086 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1087 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1088 int nbOfCells=getNumberOfCells();
1089 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1090 newCi->alloc(nbOfCells+1,1);
1091 int *newci=newCi->getPointer();
1092 const int *ci=_nodal_connec_index->getConstPointer();
1093 const int *c=_nodal_connec->getConstPointer();
1095 for(int i=0;i<nbOfCells;i++)
1097 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1098 if(type==INTERP_KERNEL::NORM_POLYHED)
1100 if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1102 std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1103 throw INTERP_KERNEL::Exception(oss.str().c_str());
1105 std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1108 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 !";
1109 throw INTERP_KERNEL::Exception(oss.str().c_str());
1112 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)
1115 newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1117 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1118 newC->alloc(newci[nbOfCells],1);
1119 int *newc=newC->getPointer();
1120 for(int i=0;i<nbOfCells;i++)
1122 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1123 if(type==INTERP_KERNEL::NORM_POLYHED)
1125 std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1126 newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1128 for(std::size_t j=0;j<n1;j++)
1130 newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1132 newc[n1+5*j+1]=c[ci[i]+1+j];
1133 newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1134 newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1135 newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1140 newc=std::copy(c+ci[i],c+ci[i+1],newc);
1142 _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1143 _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1148 * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1149 * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1150 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1151 * to write this mesh to the MED file, its cells must be sorted using
1152 * sortCellsInMEDFileFrmt().
1153 * \return \c true if at least one cell has been converted, \c false else. In the
1154 * last case the nodal connectivity remains unchanged.
1155 * \throw If the coordinates array is not set.
1156 * \throw If the nodal connectivity of cells is not defined.
1157 * \throw If \a this->getMeshDimension() < 0.
1159 bool MEDCouplingUMesh::unPolyze()
1161 checkFullyDefined();
1162 int mdim=getMeshDimension();
1164 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1167 int nbOfCells=getNumberOfCells();
1170 int initMeshLgth=getMeshLength();
1171 int *conn=_nodal_connec->getPointer();
1172 int *index=_nodal_connec_index->getPointer();
1177 for(int i=0;i<nbOfCells;i++)
1179 lgthOfCurCell=index[i+1]-posOfCurCell;
1180 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1181 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1182 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1186 switch(cm.getDimension())
1190 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1191 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1192 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1197 int nbOfFaces,lgthOfPolyhConn;
1198 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1199 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1204 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1208 ret=ret || (newType!=type);
1209 conn[newPos]=newType;
1211 posOfCurCell=index[i+1];
1216 std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1217 newPos+=lgthOfCurCell;
1218 posOfCurCell+=lgthOfCurCell;
1222 if(newPos!=initMeshLgth)
1223 _nodal_connec->reAlloc(newPos);
1230 * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1231 * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1232 * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells.
1234 * \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
1237 void MEDCouplingUMesh::simplifyPolyhedra(double eps) throw(INTERP_KERNEL::Exception)
1239 checkFullyDefined();
1240 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1241 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1242 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1243 coords->recenterForMaxPrecision(eps);
1245 int nbOfCells=getNumberOfCells();
1246 const int *conn=_nodal_connec->getConstPointer();
1247 const int *index=_nodal_connec_index->getConstPointer();
1248 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1249 connINew->alloc(nbOfCells+1,1);
1250 int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1251 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1253 for(int i=0;i<nbOfCells;i++,connINewPtr++)
1255 if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1257 SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1261 connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1262 *connINewPtr=connNew->getNumberOfTuples();
1265 setConnectivity(connNew,connINew,false);
1269 * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1270 * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1271 * the format of returned DataArrayInt instance.
1273 * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1274 * \sa MEDCouplingUMesh::getNodeIdsInUse
1276 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const throw(INTERP_KERNEL::Exception)
1278 checkConnectivityFullyDefined();
1279 int nbOfCells=getNumberOfCells();
1280 const int *connIndex=_nodal_connec_index->getConstPointer();
1281 const int *conn=_nodal_connec->getConstPointer();
1282 const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1283 int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1284 std::vector<bool> retS(maxElt,false);
1285 for(int i=0;i<nbOfCells;i++)
1286 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1290 for(int i=0;i<maxElt;i++)
1293 DataArrayInt *ret=DataArrayInt::New();
1295 int *retPtr=ret->getPointer();
1296 for(int i=0;i<maxElt;i++)
1303 * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1304 * \sa MEDCouplingUMesh::getNodeIdsInUse
1306 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const throw(INTERP_KERNEL::Exception)
1308 int nbOfNodes=(int)nodeIdsInUse.size();
1309 int nbOfCells=getNumberOfCells();
1310 const int *connIndex=_nodal_connec_index->getConstPointer();
1311 const int *conn=_nodal_connec->getConstPointer();
1312 for(int i=0;i<nbOfCells;i++)
1313 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1316 if(conn[j]<nbOfNodes)
1317 nodeIdsInUse[conn[j]]=true;
1320 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1321 throw INTERP_KERNEL::Exception(oss.str().c_str());
1327 * Finds nodes not used in any cell and returns an array giving a new id to every node
1328 * by excluding the unused nodes, for which the array holds -1. The result array is
1329 * a mapping in "Old to New" mode.
1330 * \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1331 * \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1332 * this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1333 * if the node is unused or a new id else. The caller is to delete this
1334 * array using decrRef() as it is no more needed.
1335 * \throw If the coordinates array is not set.
1336 * \throw If the nodal connectivity of cells is not defined.
1337 * \throw If the nodal connectivity includes an invalid id.
1339 * \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1340 * \ref py_mcumesh_getNodeIdsInUse "Here is a Python example".
1341 * \sa computeNodeIdsAlg()
1343 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const throw(INTERP_KERNEL::Exception)
1346 int nbOfNodes=getNumberOfNodes();
1347 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1348 ret->alloc(nbOfNodes,1);
1349 int *traducer=ret->getPointer();
1350 std::fill(traducer,traducer+nbOfNodes,-1);
1351 int nbOfCells=getNumberOfCells();
1352 const int *connIndex=_nodal_connec_index->getConstPointer();
1353 const int *conn=_nodal_connec->getConstPointer();
1354 for(int i=0;i<nbOfCells;i++)
1355 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1358 if(conn[j]<nbOfNodes)
1359 traducer[conn[j]]=1;
1362 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1363 throw INTERP_KERNEL::Exception(oss.str().c_str());
1366 nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1367 std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1372 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1373 * For each cell in \b this the number of nodes constituting cell is computed.
1374 * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1375 * So for pohyhedrons some nodes can be counted several times in the returned result.
1377 * \return a newly allocated array
1379 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
1381 checkConnectivityFullyDefined();
1382 int nbOfCells=getNumberOfCells();
1383 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1384 ret->alloc(nbOfCells,1);
1385 int *retPtr=ret->getPointer();
1386 const int *conn=getNodalConnectivity()->getConstPointer();
1387 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1388 for(int i=0;i<nbOfCells;i++,retPtr++)
1390 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1391 *retPtr=connI[i+1]-connI[i]-1;
1393 *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1399 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1400 * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1402 * \return a newly allocated array
1404 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const throw(INTERP_KERNEL::Exception)
1406 checkConnectivityFullyDefined();
1407 int nbOfCells=getNumberOfCells();
1408 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1409 ret->alloc(nbOfCells,1);
1410 int *retPtr=ret->getPointer();
1411 const int *conn=getNodalConnectivity()->getConstPointer();
1412 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1413 for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1415 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1416 *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1422 * Removes unused nodes (the node coordinates array is shorten) and returns an array
1423 * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1424 * array mean that the corresponding old node is no more used.
1425 * \return DataArrayInt * - a new instance of DataArrayInt of length \a
1426 * this->getNumberOfNodes() before call of this method. The caller is to
1427 * delete this array using decrRef() as it is no more needed.
1428 * \throw If the coordinates array is not set.
1429 * \throw If the nodal connectivity of cells is not defined.
1430 * \throw If the nodal connectivity includes an invalid id.
1432 * \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1433 * \ref py_mcumesh_zipCoordsTraducer "Here is a Python example".
1435 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer() throw(INTERP_KERNEL::Exception)
1437 int newNbOfNodes=-1;
1438 DataArrayInt *traducer=getNodeIdsInUse(newNbOfNodes);
1439 renumberNodes(traducer->getConstPointer(),newNbOfNodes);
1444 * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1445 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1447 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1452 return AreCellsEqual0(conn,connI,cell1,cell2);
1454 return AreCellsEqual1(conn,connI,cell1,cell2);
1456 return AreCellsEqual2(conn,connI,cell1,cell2);
1458 return AreCellsEqual3(conn,connI,cell1,cell2);
1460 return AreCellsEqual7(conn,connI,cell1,cell2);
1462 throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1466 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1468 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1470 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1471 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1476 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1478 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1480 int sz=connI[cell1+1]-connI[cell1];
1481 if(sz==connI[cell2+1]-connI[cell2])
1483 if(conn[connI[cell1]]==conn[connI[cell2]])
1485 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1486 unsigned dim=cm.getDimension();
1492 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1493 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1494 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1495 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1496 return work!=tmp+sz1?1:0;
1499 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1502 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1509 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1511 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1513 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1515 if(conn[connI[cell1]]==conn[connI[cell2]])
1517 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1518 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1526 * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1528 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1530 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1532 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1533 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1540 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1542 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1544 int sz=connI[cell1+1]-connI[cell1];
1545 if(sz==connI[cell2+1]-connI[cell2])
1547 if(conn[connI[cell1]]==conn[connI[cell2]])
1549 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1550 unsigned dim=cm.getDimension();
1556 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1557 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1558 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1559 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1564 std::reverse_iterator<int *> it1((int *)tmp+sz1);
1565 std::reverse_iterator<int *> it2((int *)tmp);
1566 if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1572 return work!=tmp+sz1?1:0;
1575 {//case of SEG2 and SEG3
1576 if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1578 if(!cm.isQuadratic())
1580 std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1581 std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1582 if(std::equal(it1,it2,conn+connI[cell2]+1))
1588 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])
1595 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1602 * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1603 * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1604 * and result remains unchanged.
1605 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1606 * If in 'candidates' pool -1 value is considered as an empty value.
1607 * WARNING this method returns only ONE set of result !
1609 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1611 if(candidates.size()<1)
1614 std::vector<int>::const_iterator iter=candidates.begin();
1615 int start=(*iter++);
1616 for(;iter!=candidates.end();iter++)
1618 int status=AreCellsEqual(conn,connI,start,*iter,compType);
1623 result->pushBackSilent(start);
1627 result->pushBackSilent(*iter);
1629 result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1636 * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1637 * This method keeps the coordiantes of \a this. This method is time consuming and is called
1639 * \param [in] compType input specifying the technique used to compare cells each other.
1640 * - 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.
1641 * - 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)
1642 * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1643 * - 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
1644 * can be used for users not sensitive to orientation of cell
1645 * \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.
1646 * \param [out] commonCells
1647 * \param [out] commonCellsI
1648 * \return the correspondance array old to new in a newly allocated array.
1651 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const throw(INTERP_KERNEL::Exception)
1653 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1654 getReverseNodalConnectivity(revNodal,revNodalI);
1655 FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1658 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1659 DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) throw(INTERP_KERNEL::Exception)
1661 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1662 int nbOfCells=nodalI->getNumberOfTuples()-1;
1663 commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1664 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1665 const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1666 std::vector<bool> isFetched(nbOfCells,false);
1669 for(int i=0;i<nbOfCells;i++)
1673 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1674 std::vector<int> v,v2;
1675 if(connOfNode!=connPtr+connIPtr[i+1])
1677 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1678 v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1681 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1685 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1686 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1687 v2.resize(std::distance(v2.begin(),it));
1691 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1693 int pos=commonCellsI->back();
1694 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1695 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1696 isFetched[*it]=true;
1704 for(int i=startCellId;i<nbOfCells;i++)
1708 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1709 std::vector<int> v,v2;
1710 if(connOfNode!=connPtr+connIPtr[i+1])
1712 v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1715 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1719 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1720 v2.resize(std::distance(v2.begin(),it));
1724 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1726 int pos=commonCellsI->back();
1727 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1728 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1729 isFetched[*it]=true;
1735 commonCellsArr=commonCells.retn();
1736 commonCellsIArr=commonCellsI.retn();
1740 * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1741 * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1742 * than \a other->getNumberOfCells() in the returned array means that there is no
1743 * corresponding cell in \a this mesh.
1744 * It is expected that \a this and \a other meshes share the same node coordinates
1745 * array, if it is not so an exception is thrown.
1746 * \param [in] other - the mesh to compare with.
1747 * \param [in] compType - specifies a cell comparison technique. For meaning of its
1748 * valid values [0,1,2], see zipConnectivityTraducer().
1749 * \param [out] arr - a new instance of DataArrayInt returning correspondence
1750 * between cells of the two meshes. It contains \a other->getNumberOfCells()
1751 * values. The caller is to delete this array using
1752 * decrRef() as it is no more needed.
1753 * \return bool - \c true if all cells of \a other mesh are present in the \a this
1756 * \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1757 * \ref py_mcumesh_areCellsIncludedIn "Here is a Python example".
1758 * \sa checkDeepEquivalOnSameNodesWith()
1759 * \sa checkGeoEquivalWith()
1761 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1763 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1764 int nbOfCells=getNumberOfCells();
1765 static const int possibleCompType[]={0,1,2};
1766 if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1768 std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1769 std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1771 throw INTERP_KERNEL::Exception(oss.str().c_str());
1773 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1774 arr=o2n->substr(nbOfCells);
1775 arr->setName(other->getName());
1777 if(other->getNumberOfCells()==0)
1779 return arr->getMaxValue(tmp)<nbOfCells;
1783 * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1784 * This method tries to determine if \b other is fully included in \b this.
1785 * The main difference is that this method is not expected to throw exception.
1786 * This method has two outputs :
1788 * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1789 * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1791 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1793 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1794 DataArrayInt *commonCells=0,*commonCellsI=0;
1795 int thisNbCells=getNumberOfCells();
1796 mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1797 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1798 const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1799 int otherNbCells=other->getNumberOfCells();
1800 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1801 arr2->alloc(otherNbCells,1);
1802 arr2->fillWithZero();
1803 int *arr2Ptr=arr2->getPointer();
1804 int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1805 for(int i=0;i<nbOfCommon;i++)
1807 int start=commonCellsPtr[commonCellsIPtr[i]];
1808 if(start<thisNbCells)
1810 for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1812 int sig=commonCellsPtr[j]>0?1:-1;
1813 int val=std::abs(commonCellsPtr[j])-1;
1814 if(val>=thisNbCells)
1815 arr2Ptr[val-thisNbCells]=sig*(start+1);
1819 arr2->setName(other->getName());
1820 if(arr2->presenceOfValue(0))
1827 * Merges nodes equal within \a precision and returns an array describing the
1828 * permutation used to remove duplicate nodes.
1829 * \param [in] precision - minimal absolute distance between two nodes at which they are
1830 * considered not coincident.
1831 * \param [out] areNodesMerged - is set to \c true if any coincident nodes removed.
1832 * \param [out] newNbOfNodes - number of nodes remaining after the removal.
1833 * \return DataArrayInt * - the permutation array in "Old to New" mode. For more
1834 * info on "Old to New" mode see \ref MEDCouplingArrayRenumbering. The caller
1835 * is to delete this array using decrRef() as it is no more needed.
1836 * \throw If the coordinates array is not set.
1837 * \throw If the nodal connectivity of cells is not defined.
1839 * \ref cpp_mcumesh_mergeNodes "Here is a C++ example".<br>
1840 * \ref py_mcumesh_mergeNodes "Here is a Python example".
1842 DataArrayInt *MEDCouplingUMesh::mergeNodes(double precision, bool& areNodesMerged, int& newNbOfNodes)
1844 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
1846 renumberNodes(ret->begin(),newNbOfNodes);
1852 * Merges nodes equal within \a precision and returns an array describing the
1853 * permutation used to remove duplicate nodes. In contrast to mergeNodes(), location
1854 * of merged nodes is changed to be at their barycenter.
1855 * \param [in] precision - minimal absolute distance between two nodes at which they are
1856 * considered not coincident.
1857 * \param [out] areNodesMerged - is set to \c true if any coincident nodes removed.
1858 * \param [out] newNbOfNodes - number of nodes remaining after the removal.
1859 * \return DataArrayInt * - the permutation array in "Old to New" mode. For more
1860 * info on "Old to New" mode see \ref MEDCouplingArrayRenumbering. The caller
1861 * is to delete this array using decrRef() as it is no more needed.
1862 * \throw If the coordinates array is not set.
1863 * \throw If the nodal connectivity of cells is not defined.
1865 * \ref cpp_mcumesh_mergeNodes "Here is a C++ example".<br>
1866 * \ref py_mcumesh_mergeNodes "Here is a Python example".
1868 DataArrayInt *MEDCouplingUMesh::mergeNodes2(double precision, bool& areNodesMerged, int& newNbOfNodes)
1870 DataArrayInt *ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
1872 renumberNodes2(ret->getConstPointer(),newNbOfNodes);
1876 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1879 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1880 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1882 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1883 std::vector<const MEDCouplingUMesh *> ms(2);
1886 return MergeUMeshesOnSameCoords(ms);
1890 * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1891 * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1892 * cellIds is not given explicitely but by a range python like.
1894 * \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.
1895 * \return a newly allocated
1897 * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1898 * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1900 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const throw(INTERP_KERNEL::Exception)
1902 if(getMeshDimension()!=-1)
1903 return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
1906 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
1908 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1910 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1912 return const_cast<MEDCouplingUMesh *>(this);
1917 * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
1918 * The result mesh shares or not the node coordinates array with \a this mesh depending
1919 * on \a keepCoords parameter.
1920 * \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
1921 * to write this mesh to the MED file, its cells must be sorted using
1922 * sortCellsInMEDFileFrmt().
1923 * \param [in] begin - an array of cell ids to include to the new mesh.
1924 * \param [in] end - a pointer to last-plus-one-th element of \a begin.
1925 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
1926 * array of \a this mesh, else "free" nodes are removed from the result mesh
1927 * by calling zipCoords().
1928 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
1929 * to delete this mesh using decrRef() as it is no more needed.
1930 * \throw If the coordinates array is not set.
1931 * \throw If the nodal connectivity of cells is not defined.
1932 * \throw If any cell id in the array \a begin is not valid.
1934 * \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
1935 * \ref py_mcumesh_buildPartOfMySelf "Here is a Python example".
1937 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
1939 if(getMeshDimension()!=-1)
1940 return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
1944 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1946 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1948 return const_cast<MEDCouplingUMesh *>(this);
1953 * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
1955 * 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.
1956 * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
1957 * The number of cells of \b this will remain the same with this method.
1959 * \param [in] begin begin of cell ids (included) of cells in this to assign
1960 * \param [in] end end of cell ids (excluded) of cells in this to assign
1961 * \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 ).
1962 * Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
1964 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
1966 checkConnectivityFullyDefined();
1967 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1968 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1969 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
1970 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
1972 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
1973 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
1974 throw INTERP_KERNEL::Exception(oss.str().c_str());
1976 int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
1977 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
1979 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
1980 throw INTERP_KERNEL::Exception(oss.str().c_str());
1982 int nbOfCells=getNumberOfCells();
1983 bool easyAssign=true;
1984 const int *connI=_nodal_connec_index->getConstPointer();
1985 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
1986 for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
1988 if(*it>=0 && *it<nbOfCells)
1990 easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
1994 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
1995 throw INTERP_KERNEL::Exception(oss.str().c_str());
2000 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2005 DataArrayInt *arrOut=0,*arrIOut=0;
2006 MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2008 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2009 setConnectivity(arrOut,arrIOut,true);
2013 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
2015 checkConnectivityFullyDefined();
2016 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2017 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2018 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2019 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2021 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2022 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2023 throw INTERP_KERNEL::Exception(oss.str().c_str());
2025 int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2026 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2028 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2029 throw INTERP_KERNEL::Exception(oss.str().c_str());
2031 int nbOfCells=getNumberOfCells();
2032 bool easyAssign=true;
2033 const int *connI=_nodal_connec_index->getConstPointer();
2034 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2036 for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2038 if(it>=0 && it<nbOfCells)
2040 easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2044 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2045 throw INTERP_KERNEL::Exception(oss.str().c_str());
2050 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2055 DataArrayInt *arrOut=0,*arrIOut=0;
2056 MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2058 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2059 setConnectivity(arrOut,arrIOut,true);
2064 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2065 * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2066 * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2067 * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2069 * \param [in] begin input start of array of node ids.
2070 * \param [in] end input end of array of node ids.
2071 * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2072 * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2074 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2076 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2077 checkConnectivityFullyDefined();
2079 int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2080 std::vector<bool> fastFinder(sz,false);
2081 for(const int *work=begin;work!=end;work++)
2082 if(*work>=0 && *work<sz)
2083 fastFinder[*work]=true;
2084 int nbOfCells=getNumberOfCells();
2085 const int *conn=getNodalConnectivity()->getConstPointer();
2086 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2087 for(int i=0;i<nbOfCells;i++)
2089 int ref=0,nbOfHit=0;
2090 for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2094 if(fastFinder[*work2])
2097 if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2098 cellIdsKept->pushBackSilent(i);
2100 cellIdsKeptArr=cellIdsKept.retn();
2104 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2105 * this->getMeshDimension(), that bound some cells of \a this mesh.
2106 * The cells of lower dimension to include to the result mesh are selected basing on
2107 * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2108 * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2109 * ==\c false, a cell is copied if any its node is in the array of node ids. The
2110 * created mesh shares the node coordinates array with \a this mesh.
2111 * \param [in] begin - the array of node ids.
2112 * \param [in] end - a pointer to the (last+1)-th element of \a begin.
2113 * \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2114 * array \a begin are added, else cells whose any node is in the
2115 * array \a begin are added.
2116 * \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2117 * to delete this mesh using decrRef() as it is no more needed.
2118 * \throw If the coordinates array is not set.
2119 * \throw If the nodal connectivity of cells is not defined.
2120 * \throw If any node id in \a begin is not valid.
2122 * \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2123 * \ref py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2125 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2127 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2128 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2129 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2130 desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2131 return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2135 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2136 * this->getMeshDimension(), which bound only one cell of \a this mesh.
2137 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2138 * array of \a this mesh, else "free" nodes are removed from the result mesh
2139 * by calling zipCoords().
2140 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2141 * to delete this mesh using decrRef() as it is no more needed.
2142 * \throw If the coordinates array is not set.
2143 * \throw If the nodal connectivity of cells is not defined.
2145 * \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2146 * \ref py_mcumesh_buildBoundaryMesh "Here is a Python example".
2148 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2150 DataArrayInt *desc=DataArrayInt::New();
2151 DataArrayInt *descIndx=DataArrayInt::New();
2152 DataArrayInt *revDesc=DataArrayInt::New();
2153 DataArrayInt *revDescIndx=DataArrayInt::New();
2155 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2158 descIndx->decrRef();
2159 int nbOfCells=meshDM1->getNumberOfCells();
2160 const int *revDescIndxC=revDescIndx->getConstPointer();
2161 std::vector<int> boundaryCells;
2162 for(int i=0;i<nbOfCells;i++)
2163 if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2164 boundaryCells.push_back(i);
2165 revDescIndx->decrRef();
2166 MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2171 * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2172 * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2173 * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown.
2175 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const throw(INTERP_KERNEL::Exception)
2177 checkFullyDefined();
2178 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2179 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2180 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2181 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2183 buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2184 desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2186 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2187 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2188 const int *revDescPtr=revDesc->getConstPointer();
2189 const int *revDescIndxPtr=revDescIndx->getConstPointer();
2190 int nbOfCells=getNumberOfCells();
2191 std::vector<bool> ret1(nbOfCells,false);
2193 for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2194 if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2195 { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2197 DataArrayInt *ret2=DataArrayInt::New();
2199 int *ret2Ptr=ret2->getPointer();
2201 for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2204 ret2->setName("BoundaryCells");
2209 * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2210 * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2211 * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2212 * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2214 * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2215 * This method method returns cells ids set s = s1 + s2 where :
2217 * - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2218 * - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2220 * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2221 * are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2223 * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2224 * \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
2225 * cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2227 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const throw(INTERP_KERNEL::Exception)
2229 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2230 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2231 checkConnectivityFullyDefined();
2232 otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2233 if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2234 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2235 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2236 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2237 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2238 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2239 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2240 const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2241 DataArrayInt *idsOtherInConsti=0;
2242 bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2243 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2245 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2247 for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2248 s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2249 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2250 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2251 DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2252 ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2253 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2254 ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2255 neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2256 RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2257 neighThisPartAuto=0;
2258 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2259 const int li[2]={0,1};
2260 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2261 s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2262 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2265 cellIdsRk0=s0arr.retn();
2266 cellIdsRk1=s_renum1.retn();
2270 * 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
2271 * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2273 * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2275 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const throw(INTERP_KERNEL::Exception)
2277 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2278 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2279 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2280 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2282 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2283 revDesc=0; desc=0; descIndx=0;
2284 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2285 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2286 return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2290 * Finds nodes lying on the boundary of \a this mesh.
2291 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2292 * nodes. The caller is to delete this array using decrRef() as it is no
2294 * \throw If the coordinates array is not set.
2295 * \throw If the nodal connectivity of cells is node defined.
2297 * \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2298 * \ref py_mcumesh_findBoundaryNodes "Here is a Python example".
2300 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2302 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2303 return skin->computeFetchedNodeIds();
2306 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const throw(INTERP_KERNEL::Exception)
2309 return const_cast<MEDCouplingUMesh *>(this);
2313 * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2314 * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2315 * 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.
2316 * 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.
2317 * 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.
2319 * \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
2320 * parameter is altered during the call.
2321 * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2322 * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2323 * \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.
2325 * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2327 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2328 DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const throw(INTERP_KERNEL::Exception)
2330 checkFullyDefined();
2331 otherDimM1OnSameCoords.checkFullyDefined();
2332 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2333 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2334 if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2335 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2336 DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2337 findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2338 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2339 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2340 s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2341 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2342 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2343 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2344 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2345 cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2347 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2348 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2349 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2350 DataArrayInt *idsTmp=0;
2351 bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2352 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2354 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2355 MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2356 DataArrayInt *tmp0=0,*tmp1=0;
2357 ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2358 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2359 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2360 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2361 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2362 cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2363 cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2365 cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2366 cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2367 nodeIdsToDuplicate=s3.retn();
2371 * This method operates a modification of the connectivity and coords in \b this.
2372 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2373 * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2374 * 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
2375 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2376 * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2378 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2380 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2381 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2383 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd) throw(INTERP_KERNEL::Exception)
2385 int nbOfNodes=getNumberOfNodes();
2386 duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2387 duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2391 * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2392 * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2393 * This method is a generalization of shiftNodeNumbersInConn().
2394 * \warning This method performs no check of validity of new ids. **Use it with care !**
2395 * \param [in] newNodeNumbersO2N - a permutation array, of length \a
2396 * this->getNumberOfNodes(), in "Old to New" mode.
2397 * See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2398 * \throw If the nodal connectivity of cells is not defined.
2400 * \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2401 * \ref py_mcumesh_renumberNodesInConn "Here is a Python example".
2403 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2405 checkConnectivityFullyDefined();
2406 int *conn=getNodalConnectivity()->getPointer();
2407 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2408 int nbOfCells=getNumberOfCells();
2409 for(int i=0;i<nbOfCells;i++)
2410 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2412 int& node=conn[iconn];
2413 if(node>=0)//avoid polyhedron separator
2415 node=newNodeNumbersO2N[node];
2418 _nodal_connec->declareAsNew();
2423 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2424 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2425 * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2427 * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2429 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta) throw(INTERP_KERNEL::Exception)
2431 checkConnectivityFullyDefined();
2432 int *conn=getNodalConnectivity()->getPointer();
2433 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2434 int nbOfCells=getNumberOfCells();
2435 for(int i=0;i<nbOfCells;i++)
2436 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2438 int& node=conn[iconn];
2439 if(node>=0)//avoid polyhedron separator
2444 _nodal_connec->declareAsNew();
2449 * This method operates a modification of the connectivity in \b this.
2450 * 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.
2451 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2452 * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2453 * 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
2454 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2455 * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2457 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2458 * As an another consequense after the call of this method \b this can be transiently non cohrent.
2460 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2461 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2462 * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ).
2464 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset) throw(INTERP_KERNEL::Exception)
2466 checkConnectivityFullyDefined();
2467 std::map<int,int> m;
2469 for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2471 int *conn=getNodalConnectivity()->getPointer();
2472 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2473 int nbOfCells=getNumberOfCells();
2474 for(int i=0;i<nbOfCells;i++)
2475 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2477 int& node=conn[iconn];
2478 if(node>=0)//avoid polyhedron separator
2480 std::map<int,int>::iterator it=m.find(node);
2489 * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2491 * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2492 * After the call of this method the number of cells remains the same as before.
2494 * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2495 * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2496 * be strictly in [0;this->getNumberOfCells()).
2498 * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2499 * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2500 * should be contained in[0;this->getNumberOfCells()).
2502 * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2504 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
2506 checkConnectivityFullyDefined();
2507 int nbCells=getNumberOfCells();
2508 const int *array=old2NewBg;
2510 array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2512 const int *conn=_nodal_connec->getConstPointer();
2513 const int *connI=_nodal_connec_index->getConstPointer();
2514 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2515 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2516 const int *n2oPtr=n2o->begin();
2517 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2518 newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2519 newConn->copyStringInfoFrom(*_nodal_connec);
2520 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2521 newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2522 newConnI->copyStringInfoFrom(*_nodal_connec_index);
2524 int *newC=newConn->getPointer();
2525 int *newCI=newConnI->getPointer();
2528 for(int i=0;i<nbCells;i++)
2531 int nbOfElts=connI[pos+1]-connI[pos];
2532 newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2537 setConnectivity(newConn,newConnI);
2539 free(const_cast<int *>(array));
2543 * Finds cells whose bounding boxes intersect a given bounding box.
2544 * \param [in] bbox - an array defining the bounding box via coordinates of its
2545 * extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2547 * \param [in] eps - a factor used to increase size of the bounding box of cell
2548 * before comparing it with \a bbox. This factor is multiplied by the maximal
2549 * extent of the bounding box of cell to produce an addition to this bounding box.
2550 * \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2551 * cells. The caller is to delete this array using decrRef() as it is no more
2553 * \throw If the coordinates array is not set.
2554 * \throw If the nodal connectivity of cells is not defined.
2556 * \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2557 * \ref py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2559 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2561 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2562 if(getMeshDimension()==-1)
2564 elems->pushBackSilent(0);
2565 return elems.retn();
2567 int dim=getSpaceDimension();
2568 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2569 const int* conn = getNodalConnectivity()->getConstPointer();
2570 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2571 const double* coords = getCoords()->getConstPointer();
2572 int nbOfCells=getNumberOfCells();
2573 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2575 for (int i=0; i<dim; i++)
2577 elem_bb[i*2]=std::numeric_limits<double>::max();
2578 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2581 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2583 int node= conn[inode];
2584 if(node>=0)//avoid polyhedron separator
2586 for (int idim=0; idim<dim; idim++)
2588 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2590 elem_bb[idim*2] = coords[node*dim+idim] ;
2592 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2594 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2599 if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2600 elems->pushBackSilent(ielem);
2602 return elems.retn();
2606 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2607 * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2608 * added in 'elems' parameter.
2610 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2612 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2613 if(getMeshDimension()==-1)
2615 elems->pushBackSilent(0);
2616 return elems.retn();
2618 int dim=getSpaceDimension();
2619 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2620 const int* conn = getNodalConnectivity()->getConstPointer();
2621 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2622 const double* coords = getCoords()->getConstPointer();
2623 int nbOfCells=getNumberOfCells();
2624 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2626 for (int i=0; i<dim; i++)
2628 elem_bb[i*2]=std::numeric_limits<double>::max();
2629 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2632 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2634 int node= conn[inode];
2635 if(node>=0)//avoid polyhedron separator
2637 for (int idim=0; idim<dim; idim++)
2639 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2641 elem_bb[idim*2] = coords[node*dim+idim] ;
2643 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2645 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2650 if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2651 elems->pushBackSilent(ielem);
2653 return elems.retn();
2657 * Returns a type of a cell by its id.
2658 * \param [in] cellId - the id of the cell of interest.
2659 * \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2660 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2662 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2664 const int *ptI=_nodal_connec_index->getConstPointer();
2665 const int *pt=_nodal_connec->getConstPointer();
2666 if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2667 return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2670 std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2671 throw INTERP_KERNEL::Exception(oss.str().c_str());
2676 * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2677 * This method does not throw exception if geometric type \a type is not in \a this.
2678 * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2679 * The coordinates array is not considered here.
2681 * \param [in] type the geometric type
2682 * \return cell ids in this having geometric type \a type.
2684 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception)
2687 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2689 checkConnectivityFullyDefined();
2690 int nbCells=getNumberOfCells();
2691 int mdim=getMeshDimension();
2692 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2693 if(mdim!=(int)cm.getDimension())
2694 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2695 const int *ptI=_nodal_connec_index->getConstPointer();
2696 const int *pt=_nodal_connec->getConstPointer();
2697 for(int i=0;i<nbCells;i++)
2699 if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2700 ret->pushBackSilent(i);
2706 * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2708 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2710 const int *ptI=_nodal_connec_index->getConstPointer();
2711 const int *pt=_nodal_connec->getConstPointer();
2712 int nbOfCells=getNumberOfCells();
2714 for(int i=0;i<nbOfCells;i++)
2715 if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2721 * Returns the nodal connectivity of a given cell.
2722 * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2723 * all returned node ids can be used in getCoordinatesOfNode().
2724 * \param [in] cellId - an id of the cell of interest.
2725 * \param [in,out] conn - a vector where the node ids are appended. It is not
2726 * cleared before the appending.
2727 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2729 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2731 const int *ptI=_nodal_connec_index->getConstPointer();
2732 const int *pt=_nodal_connec->getConstPointer();
2733 for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2738 std::string MEDCouplingUMesh::simpleRepr() const
2740 static const char msg0[]="No coordinates specified !";
2741 std::ostringstream ret;
2742 ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2743 ret << "Description of mesh : \"" << getDescription() << "\"\n";
2745 double tt=getTime(tmpp1,tmpp2);
2746 ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2747 ret << "Iteration : " << tmpp1 << " Order : " << tmpp2 << "\n";
2749 { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2751 { ret << " Mesh dimension has not been set or is invalid !"; }
2754 const int spaceDim=getSpaceDimension();
2755 ret << spaceDim << "\nInfo attached on space dimension : ";
2756 for(int i=0;i<spaceDim;i++)
2757 ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2761 ret << msg0 << "\n";
2762 ret << "Number of nodes : ";
2764 ret << getNumberOfNodes() << "\n";
2766 ret << msg0 << "\n";
2767 ret << "Number of cells : ";
2768 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2769 ret << getNumberOfCells() << "\n";
2771 ret << "No connectivity specified !" << "\n";
2772 ret << "Cell types present : ";
2773 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2775 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2776 ret << cm.getRepr() << " ";
2782 std::string MEDCouplingUMesh::advancedRepr() const
2784 std::ostringstream ret;
2785 ret << simpleRepr();
2786 ret << "\nCoordinates array : \n___________________\n\n";
2788 _coords->reprWithoutNameStream(ret);
2790 ret << "No array set !\n";
2791 ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2792 reprConnectivityOfThisLL(ret);
2797 * This method returns a C++ code that is a dump of \a this.
2798 * This method will throw if this is not fully defined.
2800 std::string MEDCouplingUMesh::cppRepr() const throw(INTERP_KERNEL::Exception)
2802 static const char coordsName[]="coords";
2803 static const char connName[]="conn";
2804 static const char connIName[]="connI";
2805 checkFullyDefined();
2806 std::ostringstream ret; ret << "// coordinates" << std::endl;
2807 _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2808 _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2809 _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2810 ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2811 ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2812 ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2813 ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2817 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2819 std::ostringstream ret;
2820 reprConnectivityOfThisLL(ret);
2825 * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
2826 * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2827 * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2830 * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2831 * 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
2832 * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2834 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const throw(INTERP_KERNEL::Exception)
2836 int mdim=getMeshDimension();
2838 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2839 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
2840 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
2841 bool needToCpyCT=true;
2844 tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2852 if(!_nodal_connec_index)
2854 tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2859 tmp2=_nodal_connec_index;
2862 ret->setConnectivity(tmp1,tmp2,false);
2867 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2868 ret->setCoords(coords);
2871 ret->setCoords(_coords);
2875 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
2877 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2879 int nbOfCells=getNumberOfCells();
2880 const int *c=_nodal_connec->getConstPointer();
2881 const int *ci=_nodal_connec_index->getConstPointer();
2882 for(int i=0;i<nbOfCells;i++)
2884 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
2885 stream << "Cell #" << i << " " << cm.getRepr() << " : ";
2886 std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
2891 stream << "Connectivity not defined !\n";
2894 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
2896 const int *ptI=_nodal_connec_index->getConstPointer();
2897 const int *pt=_nodal_connec->getConstPointer();
2898 if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
2899 return ptI[cellId+1]-ptI[cellId]-1;
2901 return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
2905 * Returns types of cells of the specified part of \a this mesh.
2906 * This method avoids computing sub-mesh explicitely to get its types.
2907 * \param [in] begin - an array of cell ids of interest.
2908 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
2909 * \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
2910 * describing the cell types.
2911 * \throw If the coordinates array is not set.
2912 * \throw If the nodal connectivity of cells is not defined.
2915 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
2917 checkFullyDefined();
2918 std::set<INTERP_KERNEL::NormalizedCellType> ret;
2919 const int *conn=_nodal_connec->getConstPointer();
2920 const int *connIndex=_nodal_connec_index->getConstPointer();
2921 for(const int *w=begin;w!=end;w++)
2922 ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
2927 * Defines the nodal connectivity using given connectivity arrays. Optionally updates
2928 * a set of types of cells constituting \a this mesh.
2929 * This method is for advanced users having prepared their connectivity before. For
2930 * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
2931 * \param [in] conn - the nodal connectivity array.
2932 * \param [in] connIndex - the nodal connectivity index array.
2933 * \param [in] isComputingTypes - if \c true, the set of types constituting \a this
2936 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
2938 DataArrayInt::SetArrayIn(conn,_nodal_connec);
2939 DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
2940 if(isComputingTypes)
2946 * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
2947 * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
2949 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
2950 _nodal_connec(0),_nodal_connec_index(0),
2951 _types(other._types)
2953 if(other._nodal_connec)
2954 _nodal_connec=other._nodal_connec->performCpy(deepCopy);
2955 if(other._nodal_connec_index)
2956 _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
2959 MEDCouplingUMesh::~MEDCouplingUMesh()
2962 _nodal_connec->decrRef();
2963 if(_nodal_connec_index)
2964 _nodal_connec_index->decrRef();
2968 * Recomputes a set of cell types of \a this mesh. For more info see
2969 * \ref MEDCouplingUMeshNodalConnectivity.
2971 void MEDCouplingUMesh::computeTypes()
2973 if(_nodal_connec && _nodal_connec_index)
2976 const int *conn=_nodal_connec->getConstPointer();
2977 const int *connIndex=_nodal_connec_index->getConstPointer();
2978 int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
2980 for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
2981 _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
2986 * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
2988 void MEDCouplingUMesh::checkFullyDefined() const throw(INTERP_KERNEL::Exception)
2990 if(!_nodal_connec_index || !_nodal_connec || !_coords)
2991 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
2995 * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
2997 void MEDCouplingUMesh::checkConnectivityFullyDefined() const throw(INTERP_KERNEL::Exception)
2999 if(!_nodal_connec_index || !_nodal_connec)
3000 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3004 * Returns a number of cells constituting \a this mesh.
3005 * \return int - the number of cells in \a this mesh.
3006 * \throw If the nodal connectivity of cells is not defined.
3008 int MEDCouplingUMesh::getNumberOfCells() const
3010 if(_nodal_connec_index)
3011 return _nodal_connec_index->getNumberOfTuples()-1;
3016 throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3020 * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3021 * mesh. For more info see \ref MEDCouplingMeshesPage.
3022 * \return int - the dimension of \a this mesh.
3023 * \throw If the mesh dimension is not defined using setMeshDimension().
3025 int MEDCouplingUMesh::getMeshDimension() const
3028 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3033 * Returns a length of the nodal connectivity array.
3034 * This method is for test reason. Normally the integer returned is not useable by
3035 * user. For more info see \ref MEDCouplingUMeshNodalConnectivity.
3036 * \return int - the length of the nodal connectivity array.
3038 int MEDCouplingUMesh::getMeshLength() const
3040 return _nodal_connec->getNbOfElems();
3044 * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3046 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3048 MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3049 tinyInfo.push_back(getMeshDimension());
3050 tinyInfo.push_back(getNumberOfCells());
3052 tinyInfo.push_back(getMeshLength());
3054 tinyInfo.push_back(-1);
3058 * First step of unserialization process.
3060 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3062 return tinyInfo[6]<=0;
3066 * Second step of serialization process.
3067 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3069 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3071 MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3073 a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3077 * Third and final step of serialization process.
3079 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3081 MEDCouplingPointSet::serialize(a1,a2);
3082 if(getMeshDimension()>-1)
3084 a1=DataArrayInt::New();
3085 a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3086 int *ptA1=a1->getPointer();
3087 const int *conn=getNodalConnectivity()->getConstPointer();
3088 const int *index=getNodalConnectivityIndex()->getConstPointer();
3089 ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3090 std::copy(conn,conn+getMeshLength(),ptA1);
3097 * Second and final unserialization process.
3098 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3100 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3102 MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3103 setMeshDimension(tinyInfo[5]);
3107 const int *recvBuffer=a1->getConstPointer();
3108 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3109 myConnecIndex->alloc(tinyInfo[6]+1,1);
3110 std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3111 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3112 myConnec->alloc(tinyInfo[7],1);
3113 std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3114 setConnectivity(myConnec, myConnecIndex);
3119 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3120 * CellIds are given using range specified by a start an end and step.
3122 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3124 checkFullyDefined();
3125 int ncell=getNumberOfCells();
3126 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3127 ret->_mesh_dim=_mesh_dim;
3128 ret->setCoords(_coords);
3129 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3130 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3131 int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3133 const int *conn=_nodal_connec->getConstPointer();
3134 const int *connIndex=_nodal_connec_index->getConstPointer();
3135 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3137 if(work>=0 && work<ncell)
3139 newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3143 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3144 throw INTERP_KERNEL::Exception(oss.str().c_str());
3147 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3148 int *newConnPtr=newConn->getPointer();
3149 std::set<INTERP_KERNEL::NormalizedCellType> types;
3151 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3153 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3154 newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3156 ret->setConnectivity(newConn,newConnI,false);
3158 ret->copyTinyInfoFrom(this);
3163 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3164 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3165 * The return newly allocated mesh will share the same coordinates as \a this.
3167 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3169 checkFullyDefined();
3170 int ncell=getNumberOfCells();
3171 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3172 ret->_mesh_dim=_mesh_dim;
3173 ret->setCoords(_coords);
3174 std::size_t nbOfElemsRet=std::distance(begin,end);
3175 int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3177 const int *conn=_nodal_connec->getConstPointer();
3178 const int *connIndex=_nodal_connec_index->getConstPointer();
3180 for(const int *work=begin;work!=end;work++,newNbring++)
3182 if(*work>=0 && *work<ncell)
3183 connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3187 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3188 throw INTERP_KERNEL::Exception(oss.str().c_str());
3191 int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3192 int *connRetWork=connRet;
3193 std::set<INTERP_KERNEL::NormalizedCellType> types;
3194 for(const int *work=begin;work!=end;work++)
3196 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3197 connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3199 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3200 connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3201 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3202 connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3203 ret->setConnectivity(connRetArr,connIndexRetArr,false);
3205 ret->copyTinyInfoFrom(this);
3210 * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3212 * For 1D cells, the returned field contains lengths.<br>
3213 * For 2D cells, the returned field contains areas.<br>
3214 * For 3D cells, the returned field contains volumes.
3215 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3216 * orientation, i.e. the volume is always positive.
3217 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3218 * and one time . The caller is to delete this field using decrRef() as it is no
3221 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3223 std::string name="MeasureOfMesh_";
3225 int nbelem=getNumberOfCells();
3226 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3227 field->setName(name.c_str());
3228 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3229 array->alloc(nbelem,1);
3230 double *area_vol=array->getPointer();
3231 field->setArray(array) ; array=0;
3232 field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3233 field->synchronizeTimeWithMesh();
3234 if(getMeshDimension()!=-1)
3237 INTERP_KERNEL::NormalizedCellType type;
3238 int dim_space=getSpaceDimension();
3239 const double *coords=getCoords()->getConstPointer();
3240 const int *connec=getNodalConnectivity()->getConstPointer();
3241 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3242 for(int iel=0;iel<nbelem;iel++)
3244 ipt=connec_index[iel];
3245 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3246 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);
3249 std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3253 area_vol[0]=std::numeric_limits<double>::max();
3255 return field.retn();
3259 * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3261 * For 1D cells, the returned array contains lengths.<br>
3262 * For 2D cells, the returned array contains areas.<br>
3263 * For 3D cells, the returned array contains volumes.
3264 * This method avoids building explicitly a part of \a this mesh to perform the work.
3265 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3266 * orientation, i.e. the volume is always positive.
3267 * \param [in] begin - an array of cell ids of interest.
3268 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3269 * \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3270 * delete this array using decrRef() as it is no more needed.
3272 * \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3273 * \ref py_mcumesh_getPartMeasureField "Here is a Python example".
3274 * \sa getMeasureField()
3276 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3278 std::string name="PartMeasureOfMesh_";
3280 int nbelem=(int)std::distance(begin,end);
3281 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3282 array->setName(name.c_str());
3283 array->alloc(nbelem,1);
3284 double *area_vol=array->getPointer();
3285 if(getMeshDimension()!=-1)
3288 INTERP_KERNEL::NormalizedCellType type;
3289 int dim_space=getSpaceDimension();
3290 const double *coords=getCoords()->getConstPointer();
3291 const int *connec=getNodalConnectivity()->getConstPointer();
3292 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3293 for(const int *iel=begin;iel!=end;iel++)
3295 ipt=connec_index[*iel];
3296 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3297 *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3300 std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3304 area_vol[0]=std::numeric_limits<double>::max();
3306 return array.retn();
3310 * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3311 * \a this one. The returned field contains the dual cell volume for each corresponding
3312 * node in \a this mesh. In other words, the field returns the getMeasureField() of
3313 * the dual mesh in P1 sens of \a this.<br>
3314 * For 1D cells, the returned field contains lengths.<br>
3315 * For 2D cells, the returned field contains areas.<br>
3316 * For 3D cells, the returned field contains volumes.
3317 * This method is useful to check "P1*" conservative interpolators.
3318 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3319 * orientation, i.e. the volume is always positive.
3320 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3321 * nodes and one time. The caller is to delete this array using decrRef() as
3322 * it is no more needed.
3324 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3326 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3327 std::string name="MeasureOnNodeOfMesh_";
3329 int nbNodes=getNumberOfNodes();
3330 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3331 double cst=1./((double)getMeshDimension()+1.);
3332 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3333 array->alloc(nbNodes,1);
3334 double *valsToFill=array->getPointer();
3335 std::fill(valsToFill,valsToFill+nbNodes,0.);
3336 const double *values=tmp->getArray()->getConstPointer();
3337 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3338 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3339 getReverseNodalConnectivity(da,daInd);
3340 const int *daPtr=da->getConstPointer();
3341 const int *daIPtr=daInd->getConstPointer();
3342 for(int i=0;i<nbNodes;i++)
3343 for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3344 valsToFill[i]+=cst*values[*cell];
3346 ret->setArray(array);
3351 * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3352 * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3353 * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3354 * and are normalized.
3355 * <br> \a this can be either
3356 * - a 2D mesh in 2D or 3D space or
3357 * - an 1D mesh in 2D space.
3359 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3360 * cells and one time. The caller is to delete this field using decrRef() as
3361 * it is no more needed.
3362 * \throw If the nodal connectivity of cells is not defined.
3363 * \throw If the coordinates array is not set.
3364 * \throw If the mesh dimension is not set.
3365 * \throw If the mesh and space dimension is not as specified above.
3367 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3369 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3370 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3371 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3372 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3373 int nbOfCells=getNumberOfCells();
3374 int nbComp=getMeshDimension()+1;
3375 array->alloc(nbOfCells,nbComp);
3376 double *vals=array->getPointer();
3377 const int *connI=_nodal_connec_index->getConstPointer();
3378 const int *conn=_nodal_connec->getConstPointer();
3379 const double *coords=_coords->getConstPointer();
3380 if(getMeshDimension()==2)
3382 if(getSpaceDimension()==3)
3384 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3385 const double *locPtr=loc->getConstPointer();
3386 for(int i=0;i<nbOfCells;i++,vals+=3)
3388 int offset=connI[i];
3389 INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3390 double n=INTERP_KERNEL::norm<3>(vals);
3391 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3396 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3397 const double *isAbsPtr=isAbs->getArray()->begin();
3398 for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3399 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3402 else//meshdimension==1
3405 for(int i=0;i<nbOfCells;i++)
3407 int offset=connI[i];
3408 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3409 double n=INTERP_KERNEL::norm<2>(tmp);
3410 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3415 ret->setArray(array);
3417 ret->synchronizeTimeWithSupport();
3422 * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3423 * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3424 * and are normalized.
3425 * <br> \a this can be either
3426 * - a 2D mesh in 2D or 3D space or
3427 * - an 1D mesh in 2D space.
3429 * This method avoids building explicitly a part of \a this mesh to perform the work.
3430 * \param [in] begin - an array of cell ids of interest.
3431 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3432 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3433 * cells and one time. The caller is to delete this field using decrRef() as
3434 * it is no more needed.
3435 * \throw If the nodal connectivity of cells is not defined.
3436 * \throw If the coordinates array is not set.
3437 * \throw If the mesh dimension is not set.
3438 * \throw If the mesh and space dimension is not as specified above.
3439 * \sa buildOrthogonalField()
3441 * \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3442 * \ref py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3444 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3446 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3447 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3448 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3449 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3450 std::size_t nbelems=std::distance(begin,end);
3451 int nbComp=getMeshDimension()+1;
3452 array->alloc((int)nbelems,nbComp);
3453 double *vals=array->getPointer();
3454 const int *connI=_nodal_connec_index->getConstPointer();
3455 const int *conn=_nodal_connec->getConstPointer();
3456 const double *coords=_coords->getConstPointer();
3457 if(getMeshDimension()==2)
3459 if(getSpaceDimension()==3)
3461 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3462 const double *locPtr=loc->getConstPointer();
3463 for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3465 int offset=connI[*i];
3466 INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3467 double n=INTERP_KERNEL::norm<3>(vals);
3468 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3473 for(std::size_t i=0;i<nbelems;i++)
3474 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3477 else//meshdimension==1
3480 for(const int *i=begin;i!=end;i++)
3482 int offset=connI[*i];
3483 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3484 double n=INTERP_KERNEL::norm<2>(tmp);
3485 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3490 ret->setArray(array);
3492 ret->synchronizeTimeWithSupport();
3497 * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3498 * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3499 * and are \b not normalized.
3500 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3501 * cells and one time. The caller is to delete this field using decrRef() as
3502 * it is no more needed.
3503 * \throw If the nodal connectivity of cells is not defined.
3504 * \throw If the coordinates array is not set.
3505 * \throw If \a this->getMeshDimension() != 1.
3506 * \throw If \a this mesh includes cells of type other than SEG2.
3508 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3510 if(getMeshDimension()!=1)
3511 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3512 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3513 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3514 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3515 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3516 int nbOfCells=getNumberOfCells();
3517 int spaceDim=getSpaceDimension();
3518 array->alloc(nbOfCells,spaceDim);
3519 double *pt=array->getPointer();
3520 const double *coo=getCoords()->getConstPointer();
3521 std::vector<int> conn;
3523 for(int i=0;i<nbOfCells;i++)
3526 getNodeIdsOfCell(i,conn);
3527 pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3529 ret->setArray(array);
3531 ret->synchronizeTimeWithSupport();
3536 * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3537 * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3538 * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3539 * from. If a result face is shared by two 3D cells, then the face in included twice in
3541 * \param [in] origin - 3 components of a point defining location of the plane.
3542 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3543 * must be greater than 1e-6.
3544 * \param [in] eps - half-thickness of the plane.
3545 * \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3546 * producing correspondent 2D cells. The caller is to delete this array
3547 * using decrRef() as it is no more needed.
3548 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3549 * not share the node coordinates array with \a this mesh. The caller is to
3550 * delete this mesh using decrRef() as it is no more needed.
3551 * \throw If the coordinates array is not set.
3552 * \throw If the nodal connectivity of cells is not defined.
3553 * \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3554 * \throw If magnitude of \a vec is less than 1e-6.
3555 * \throw If the plane does not intersect any 3D cell of \a this mesh.
3556 * \throw If \a this includes quadratic cells.
3558 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3560 checkFullyDefined();
3561 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3562 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3563 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3564 if(candidates->empty())
3565 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3566 std::vector<int> nodes;
3567 DataArrayInt *cellIds1D=0;
3568 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3569 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3570 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3571 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3572 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3573 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3574 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3575 revDesc2=0; revDescIndx2=0;
3576 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3577 revDesc1=0; revDescIndx1=0;
3578 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3579 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3581 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3582 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3584 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3585 std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3586 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3587 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3588 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3589 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3590 connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3591 subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3592 if(cellIds2->empty())
3593 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3594 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3595 ret->setCoords(mDesc1->getCoords());
3596 ret->setConnectivity(conn,connI,true);
3597 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3602 * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3603 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
3604 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3606 * \param [in] origin - 3 components of a point defining location of the plane.
3607 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3608 * must be greater than 1e-6.
3609 * \param [in] eps - half-thickness of the plane.
3610 * \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3611 * producing correspondent segments. The caller is to delete this array
3612 * using decrRef() as it is no more needed.
3613 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3614 * mesh in 3D space. This mesh does not share the node coordinates array with
3615 * \a this mesh. The caller is to delete this mesh using decrRef() as it is
3617 * \throw If the coordinates array is not set.
3618 * \throw If the nodal connectivity of cells is not defined.
3619 * \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3620 * \throw If magnitude of \a vec is less than 1e-6.
3621 * \throw If the plane does not intersect any 2D cell of \a this mesh.
3622 * \throw If \a this includes quadratic cells.
3624 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3626 checkFullyDefined();
3627 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3628 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3629 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3630 if(candidates->empty())
3631 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3632 std::vector<int> nodes;
3633 DataArrayInt *cellIds1D=0;
3634 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3635 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3636 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3637 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3638 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3639 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3640 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3641 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3642 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3644 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3645 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3647 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3648 int ncellsSub=subMesh->getNumberOfCells();
3649 std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3650 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3651 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3652 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3653 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3655 const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3656 const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3657 for(int i=0;i<ncellsSub;i++)
3659 if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3661 if(cut3DSurf[i].first!=-2)
3663 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3664 connI->pushBackSilent(conn->getNumberOfTuples());
3665 cellIds2->pushBackSilent(i);
3669 int cellId3DSurf=cut3DSurf[i].second;
3670 int offset=nodalI[cellId3DSurf]+1;
3671 int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3672 for(int j=0;j<nbOfEdges;j++)
3674 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3675 connI->pushBackSilent(conn->getNumberOfTuples());
3676 cellIds2->pushBackSilent(cellId3DSurf);
3681 if(cellIds2->empty())
3682 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3683 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3684 ret->setCoords(mDesc1->getCoords());
3685 ret->setConnectivity(conn,connI,true);
3686 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3691 * Finds cells whose bounding boxes intersect a given plane.
3692 * \param [in] origin - 3 components of a point defining location of the plane.
3693 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3694 * must be greater than 1e-6.
3695 * \param [in] eps - half-thickness of the plane.
3696 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3697 * cells. The caller is to delete this array using decrRef() as it is no more
3699 * \throw If the coordinates array is not set.
3700 * \throw If the nodal connectivity of cells is not defined.
3701 * \throw If \a this->getSpaceDimension() != 3.
3702 * \throw If magnitude of \a vec is less than 1e-6.
3703 * \sa buildSlice3D()
3705 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const throw(INTERP_KERNEL::Exception)
3707 checkFullyDefined();
3708 if(getSpaceDimension()!=3)
3709 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3710 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3712 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3714 vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3715 double angle=acos(vec[2]/normm);
3716 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3720 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3721 MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3722 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3724 mw->getBoundingBox(bbox);
3725 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3726 cellIds=mw->getCellsInBoundingBox(bbox,eps);
3730 getBoundingBox(bbox);
3731 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3732 cellIds=getCellsInBoundingBox(bbox,eps);
3734 return cellIds.retn();
3738 * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3739 * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3740 * No consideration of coordinate is done by this method.
3741 * 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)
3742 * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3744 bool MEDCouplingUMesh::isContiguous1D() const throw(INTERP_KERNEL::Exception)
3746 if(getMeshDimension()!=1)
3747 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3748 int nbCells=getNumberOfCells();
3750 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3751 const int *connI=_nodal_connec_index->getConstPointer();
3752 const int *conn=_nodal_connec->getConstPointer();
3753 int ref=conn[connI[0]+2];
3754 for(int i=1;i<nbCells;i++)
3756 if(conn[connI[i]+1]!=ref)
3758 ref=conn[connI[i]+2];
3764 * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3765 * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3766 * \param pt reference point of the line
3767 * \param v normalized director vector of the line
3768 * \param eps max precision before throwing an exception
3769 * \param res output of size this->getNumberOfCells
3771 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3773 if(getMeshDimension()!=1)
3774 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3775 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3776 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3777 if(getSpaceDimension()!=3)
3778 throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3779 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3780 const double *fPtr=f->getArray()->getConstPointer();
3782 for(int i=0;i<getNumberOfCells();i++)
3784 const double *tmp1=fPtr+3*i;
3785 tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3786 tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3787 tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3788 double n1=INTERP_KERNEL::norm<3>(tmp);
3789 n1/=INTERP_KERNEL::norm<3>(tmp1);
3791 throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3793 const double *coo=getCoords()->getConstPointer();
3794 for(int i=0;i<getNumberOfNodes();i++)
3796 std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3797 std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3798 res[i]=std::accumulate(tmp,tmp+3,0.);
3803 * 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.
3804 * \a this is expected to be a mesh so that its space dimension is equal to its
3805 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3806 * 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).
3808 * 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
3809 * 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).
3810 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3812 * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3813 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3815 * \param [in] ptBg the start pointer (included) of the coordinates of the point
3816 * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3817 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3818 * \return the positive value of the distance.
3819 * \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
3821 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3823 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const throw(INTERP_KERNEL::Exception)
3825 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3826 if(meshDim!=spaceDim-1)
3827 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3828 if(meshDim!=2 && meshDim!=1)
3829 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3830 checkFullyDefined();
3831 if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3832 { 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()); }
3833 DataArrayInt *ret1=0;
3834 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
3835 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
3836 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
3837 cellId=*ret1Safe->begin();
3838 return *ret0->begin();
3842 * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
3843 * to \a this and the first \a cellId in \a this corresponding to the returned distance.
3844 * 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
3845 * 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).
3846 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3848 * \a this is expected to be a mesh so that its space dimension is equal to its
3849 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3850 * 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).
3852 * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
3853 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3855 * \param [in] pts the list of points in which each tuple represents a point
3856 * \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.
3857 * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
3858 * \throw if number of components of \a pts is not equal to the space dimension.
3859 * \throw if mesh dimension of \a this is not equal to space dimension - 1.
3860 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
3862 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const throw(INTERP_KERNEL::Exception)
3865 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
3866 pts->checkAllocated();
3867 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3868 if(meshDim!=spaceDim-1)
3869 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
3870 if(meshDim!=2 && meshDim!=1)
3871 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
3872 if(pts->getNumberOfComponents()!=spaceDim)
3874 std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
3875 throw INTERP_KERNEL::Exception(oss.str().c_str());
3877 checkFullyDefined();
3878 int nbCells=getNumberOfCells();
3880 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
3881 int nbOfPts=pts->getNumberOfTuples();
3882 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
3883 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
3884 const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
3885 double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
3886 std::vector<double> bbox;
3887 getBoundingBoxForBBTree(bbox);
3892 BBTreeDst<3> myTree(&bbox[0],0,0,nbCells);
3893 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
3895 double x=std::numeric_limits<double>::max();
3896 std::vector<int> elems;
3897 myTree.getMinDistanceOfMax(ptsPtr,x);
3898 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3899 DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3905 BBTreeDst<2> myTree(&bbox[0],0,0,nbCells);
3906 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
3908 double x=std::numeric_limits<double>::max();
3909 std::vector<int> elems;
3910 myTree.getMinDistanceOfMax(ptsPtr,x);
3911 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3912 DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3917 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
3919 cellIds=ret1.retn();
3924 * \param [in] pt the start pointer (included) of the coordinates of the point
3925 * \param [in] cellIdsBg the start pointer (included) of cellIds
3926 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3927 * \param [in] nc nodal connectivity
3928 * \param [in] ncI nodal connectivity index
3929 * \param [in,out] ret0 the min distance between \a this and the external input point
3930 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3931 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
3933 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) throw(INTERP_KERNEL::Exception)
3936 ret0=std::numeric_limits<double>::max();
3937 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
3939 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
3941 case INTERP_KERNEL::NORM_TRI3:
3943 double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
3945 { ret0=tmp; cellId=*zeCell; }
3948 case INTERP_KERNEL::NORM_QUAD4:
3949 case INTERP_KERNEL::NORM_POLYGON:
3951 double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
3953 { ret0=tmp; cellId=*zeCell; }
3957 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
3963 * \param [in] pt the start pointer (included) of the coordinates of the point
3964 * \param [in] cellIdsBg the start pointer (included) of cellIds
3965 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3966 * \param [in] nc nodal connectivity
3967 * \param [in] ncI nodal connectivity index
3968 * \param [in,out] ret0 the min distance between \a this and the external input point
3969 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3970 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
3972 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) throw(INTERP_KERNEL::Exception)
3975 ret0=std::numeric_limits<double>::max();
3976 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
3978 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
3980 case INTERP_KERNEL::NORM_SEG2:
3982 std::size_t uselessEntry=0;
3983 double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
3986 { ret0=tmp; cellId=*zeCell; }
3990 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
3996 * Finds cells in contact with a ball (i.e. a point with precision).
3997 * \warning This method is suitable if the caller intends to evaluate only one
3998 * point, for more points getCellsContainingPoints() is recommended as it is
4000 * \param [in] pos - array of coordinates of the ball central point.
4001 * \param [in] eps - ball radius.
4002 * \return int - a smallest id of cells being in contact with the ball, -1 in case
4003 * if there are no such cells.
4004 * \throw If the coordinates array is not set.
4005 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4007 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4009 std::vector<int> elts;
4010 getCellsContainingPoint(pos,eps,elts);
4013 return elts.front();
4017 * Finds cells in contact with a ball (i.e. a point with precision).
4018 * \warning This method is suitable if the caller intends to evaluate only one
4019 * point, for more points getCellsContainingPoints() is recommended as it is
4021 * \param [in] pos - array of coordinates of the ball central point.
4022 * \param [in] eps - ball radius.
4023 * \param [in,out] elts - vector returning ids of the found cells. It is cleared
4024 * before inserting ids.
4025 * \throw If the coordinates array is not set.
4026 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4028 * \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4029 * \ref py_mcumesh_getCellsContainingPoint "Here is a Python example".
4031 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4033 std::vector<int> eltsIndex;
4034 getCellsContainingPoints(pos,1,eps,elts,eltsIndex);
4039 namespace ParaMEDMEM
4041 template<const int SPACEDIMM>
4045 static const int MY_SPACEDIM=SPACEDIMM;
4046 static const int MY_MESHDIM=8;
4047 typedef int MyConnType;
4048 static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4050 // useless, but for windows compilation ...
4051 const double* getCoordinatesPtr() const { return 0; }
4052 const int* getConnectivityPtr() const { return 0; }
4053 const int* getConnectivityIndexPtr() const { return 0; }
4054 INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4058 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4060 INTERP_KERNEL::Edge *ret=0;
4063 case INTERP_KERNEL::NORM_SEG2:
4065 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4068 case INTERP_KERNEL::NORM_SEG3:
4070 INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4071 INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4072 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4073 bool colinearity=inters.areColinears();
4074 delete e1; delete e2;
4076 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4078 ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4079 mapp2[bg[2]].second=false;
4083 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4089 * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed be the sub set of cells in 'candidates' and the global mesh 'mDesc'.
4090 * The input meth 'mDesc' must be so that mDim==1 et spaceDim==3.
4091 * 'mapp' contains a mapping between local numbering in submesh and the global node numbering in 'mDesc'.
4093 INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates, std::map<INTERP_KERNEL::Node *,int>& mapp) throw(INTERP_KERNEL::Exception)
4096 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.
4097 const double *coo=mDesc->getCoords()->getConstPointer();
4098 const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4099 const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4101 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4102 s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4103 for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4105 INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4106 mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4108 INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4109 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4111 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4112 ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4114 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4116 if((*it2).second.second)
4117 mapp[(*it2).second.first]=(*it2).first;
4118 ((*it2).second.first)->decrRef();
4123 INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4127 int locId=nodeId-offset2;
4128 return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4132 int locId=nodeId-offset1;
4133 return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4135 return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4138 void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4139 const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4140 /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4142 for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4144 int eltId1=abs(*desc1)-1;
4145 for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4147 std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4148 if(it==mappRev.end())
4150 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4161 template<int SPACEDIM>
4162 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4163 double eps, std::vector<int>& elts, std::vector<int>& eltsIndex) const
4165 std::vector<double> bbox;
4166 eltsIndex.resize(nbOfPoints+1);
4169 getBoundingBoxForBBTree(bbox);
4170 int nbOfCells=getNumberOfCells();
4171 const int *conn=_nodal_connec->getConstPointer();
4172 const int *connI=_nodal_connec_index->getConstPointer();
4173 double bb[2*SPACEDIM];
4174 BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4175 for(int i=0;i<nbOfPoints;i++)
4177 eltsIndex[i+1]=eltsIndex[i];
4178 for(int j=0;j<SPACEDIM;j++)
4180 bb[2*j]=pos[SPACEDIM*i+j];
4181 bb[2*j+1]=pos[SPACEDIM*i+j];
4183 std::vector<int> candidates;
4184 myTree.getIntersectingElems(bb,candidates);
4185 for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4187 int sz=connI[(*iter)+1]-connI[*iter]-1;
4188 if(INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,
4189 (INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]],
4190 coords,conn+connI[*iter]+1,sz,eps))
4193 elts.push_back(*iter);
4199 * Finds cells in contact with several balls (i.e. points with precision).
4200 * This method is an extension of getCellContainingPoint() and
4201 * getCellsContainingPoint() for the case of multiple points.
4202 * \param [in] pos - an array of coordinates of points in full interlace mode :
4203 * X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4204 * this->getSpaceDimension() * \a nbOfPoints
4205 * \param [in] nbOfPoints - number of points to locate within \a this mesh.
4206 * \param [in] eps - radius of balls (i.e. the precision).
4207 * \param [in,out] elts - vector returning ids of found cells.
4208 * \param [in,out] eltsIndex - an array, of length \a nbOfPoints + 1,
4209 * dividing cell ids in \a elts into groups each referring to one
4210 * point. Its every element (except the last one) is an index pointing to the
4211 * first id of a group of cells. For example cells in contact with the *i*-th
4212 * point are described by following range of indices:
4213 * [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4214 * \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4215 * Number of cells in contact with the *i*-th point is
4216 * \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4217 * \throw If the coordinates array is not set.
4218 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4220 * \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4221 * \ref py_mcumesh_getCellsContainingPoints "Here is a Python example".
4223 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4224 std::vector<int>& elts, std::vector<int>& eltsIndex) const
4226 int spaceDim=getSpaceDimension();
4227 int mDim=getMeshDimension();
4232 const double *coords=_coords->getConstPointer();
4233 getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4240 throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4242 else if(spaceDim==2)
4246 const double *coords=_coords->getConstPointer();
4247 getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4250 throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4252 else if(spaceDim==1)
4256 const double *coords=_coords->getConstPointer();
4257 getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4260 throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4263 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4267 * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4268 * least two its edges intersect each other anywhere except their extremities. An
4269 * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4270 * \param [in,out] cells - a vector returning ids of the found cells. It is not
4271 * cleared before filling in.
4272 * \param [in] eps - precision.
4273 * \throw If \a this->getMeshDimension() != 2.
4274 * \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4276 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4278 const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4279 if(getMeshDimension()!=2)
4280 throw INTERP_KERNEL::Exception(msg);
4281 int spaceDim=getSpaceDimension();
4282 if(spaceDim!=2 && spaceDim!=3)
4283 throw INTERP_KERNEL::Exception(msg);
4284 const int *conn=_nodal_connec->getConstPointer();
4285 const int *connI=_nodal_connec_index->getConstPointer();
4286 int nbOfCells=getNumberOfCells();
4287 std::vector<double> cell2DinS2;
4288 for(int i=0;i<nbOfCells;i++)
4290 int offset=connI[i];
4291 int nbOfNodesForCell=connI[i+1]-offset-1;
4292 if(nbOfNodesForCell<=3)
4294 bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4295 project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4296 if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4303 * This method is typically requested to unbutterfly 2D linear cells in \b this.
4305 * 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.
4306 * 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.
4308 * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4309 * This convex envelop is computed using Jarvis march algorithm.
4310 * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4311 * 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)
4312 * 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.
4314 * \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.
4316 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D() throw(INTERP_KERNEL::Exception)
4318 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4319 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D works only for meshDim=2 and spaceDim=2 !");
4320 checkFullyDefined();
4321 const double *coords=getCoords()->getConstPointer();
4322 int nbOfCells=getNumberOfCells();
4323 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4324 nodalConnecIndexOut->alloc(nbOfCells+1,1);
4325 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4326 int *workIndexOut=nodalConnecIndexOut->getPointer();
4328 const int *nodalConnecIn=_nodal_connec->getConstPointer();
4329 const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4330 std::set<INTERP_KERNEL::NormalizedCellType> types;
4331 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4332 isChanged->alloc(0,1);
4333 for(int i=0;i<nbOfCells;i++,workIndexOut++)
4335 int pos=nodalConnecOut->getNumberOfTuples();
4336 if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4337 isChanged->pushBackSilent(i);
4338 types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4339 workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4341 if(isChanged->empty())
4343 setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4345 return isChanged.retn();
4349 * This method is \b NOT const because it can modify \a this.
4350 * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4351 * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4352 * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4353 * \b 1 for translation and rotation around point of 'mesh1D'.
4354 * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.
4356 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4358 checkFullyDefined();
4359 mesh1D->checkFullyDefined();
4360 if(!mesh1D->isContiguous1D())
4361 throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4362 if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4363 throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4364 if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4365 throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4366 if(mesh1D->getMeshDimension()!=1)
4367 throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4369 if(isPresenceOfQuadratic())
4371 if(mesh1D->isFullyQuadratic())
4374 throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4377 int oldNbOfNodes=getNumberOfNodes();
4378 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4383 newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4388 newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4392 throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4394 setCoords(newCoords);
4395 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4401 * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4402 * If it is not the case an exception will be thrown.
4403 * This method is non const because the coordinate of \a this can be appended with some new points issued from
4404 * intersection of plane defined by ('origin','vec').
4405 * This method has one in/out parameter : 'cut3DCurve'.
4406 * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4407 * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4408 * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4409 * This method will throw an exception if \a this contains a non linear segment.
4411 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve) throw(INTERP_KERNEL::Exception)
4413 checkFullyDefined();
4414 if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4415 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4416 int ncells=getNumberOfCells();
4417 int nnodes=getNumberOfNodes();
4418 double vec2[3],vec3[3],vec4[3];
4419 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4421 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4422 vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4423 const int *conn=_nodal_connec->getConstPointer();
4424 const int *connI=_nodal_connec_index->getConstPointer();
4425 const double *coo=_coords->getConstPointer();
4426 std::vector<double> addCoo;
4427 for(int i=0;i<ncells;i++)
4429 if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4431 if(cut3DCurve[i]==-2)
4433 int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4434 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];
4435 double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4436 double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4437 if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4439 const double *st2=coo+3*st;
4440 vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4441 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]));
4442 if(pos>eps && pos<1-eps)
4444 int nNode=((int)addCoo.size())/3;
4445 vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4446 addCoo.insert(addCoo.end(),vec4,vec4+3);
4447 cut3DCurve[i]=nnodes+nNode;
4453 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4457 int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4458 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4459 coo2->alloc(newNbOfNodes,3);
4460 double *tmp=coo2->getPointer();
4461 tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4462 std::copy(addCoo.begin(),addCoo.end(),tmp);
4463 DataArrayDouble::SetArrayIn(coo2,_coords);
4468 * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4469 * \param mesh1D is the input 1D mesh used for translation computation.
4470 * \return newCoords new coords filled by this method.
4472 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4474 int oldNbOfNodes=getNumberOfNodes();
4475 int nbOf1DCells=mesh1D->getNumberOfCells();
4476 int spaceDim=getSpaceDimension();
4477 DataArrayDouble *ret=DataArrayDouble::New();
4478 std::vector<bool> isQuads;
4479 int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4480 ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4481 double *retPtr=ret->getPointer();
4482 const double *coords=getCoords()->getConstPointer();
4483 double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4485 std::vector<double> c;
4489 for(int i=0;i<nbOf1DCells;i++)
4492 mesh1D->getNodeIdsOfCell(i,v);
4494 mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4495 mesh1D->getCoordinatesOfNode(v[0],c);
4496 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4497 for(int j=0;j<oldNbOfNodes;j++)
4498 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4502 mesh1D->getCoordinatesOfNode(v[1],c);
4503 mesh1D->getCoordinatesOfNode(v[0],c);
4504 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4505 for(int j=0;j<oldNbOfNodes;j++)
4506 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4509 ret->copyStringInfoFrom(*getCoords());
4514 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4515 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4516 * \return newCoords new coords filled by this method.
4518 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4520 if(mesh1D->getSpaceDimension()==2)
4521 return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4522 if(mesh1D->getSpaceDimension()==3)
4523 return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4524 throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4528 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4529 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4530 * \return newCoords new coords filled by this method.
4532 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4535 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4536 int oldNbOfNodes=getNumberOfNodes();
4537 int nbOf1DCells=mesh1D->getNumberOfCells();
4539 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4540 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4541 int nbOfLevsInVec=nbOf1DCells+1;
4542 ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4543 double *retPtr=ret->getPointer();
4544 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4545 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4546 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4547 tmp->setCoords(tmp2);
4548 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4549 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4550 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4551 for(int i=1;i<nbOfLevsInVec;i++)
4553 const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4554 const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4555 const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4556 const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4557 tmp->translate(vec);
4558 double tmp3[2],radius,alpha,alpha0;
4559 const double *p0=i+1<nbOfLevsInVec?begin:third;
4560 const double *p1=i+1<nbOfLevsInVec?end:begin;
4561 const double *p2=i+1<nbOfLevsInVec?third:end;
4562 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4563 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]);
4564 double angle=acos(cosangle/(radius*radius));
4565 tmp->rotate(end,0,angle);
4566 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4572 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4573 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4574 * \return newCoords new coords filled by this method.
4576 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4579 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4580 int oldNbOfNodes=getNumberOfNodes();
4581 int nbOf1DCells=mesh1D->getNumberOfCells();
4583 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4584 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4585 int nbOfLevsInVec=nbOf1DCells+1;
4586 ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4587 double *retPtr=ret->getPointer();
4588 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4589 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4590 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4591 tmp->setCoords(tmp2);
4592 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4593 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4594 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4595 for(int i=1;i<nbOfLevsInVec;i++)
4597 const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4598 const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4599 const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4600 const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4601 tmp->translate(vec);
4602 double tmp3[2],radius,alpha,alpha0;
4603 const double *p0=i+1<nbOfLevsInVec?begin:third;
4604 const double *p1=i+1<nbOfLevsInVec?end:begin;
4605 const double *p2=i+1<nbOfLevsInVec?third:end;
4606 double vecPlane[3]={
4607 (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4608 (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4609 (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4611 double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4614 vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4615 double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4616 double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4618 double c2=cos(asin(s2));
4620 {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4621 {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4622 {-vec2[1]*s2, vec2[0]*s2, c2}
4624 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]};
4625 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]};
4626 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]};
4627 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4628 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]);
4629 double angle=acos(cosangle/(radius*radius));
4630 tmp->rotate(end,vecPlane,angle);
4633 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4639 * This method is private because not easy to use for end user. This method is const contrary to
4640 * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4641 * the coords sorted slice by slice.
4642 * \param isQuad specifies presence of quadratic cells.
4644 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4646 int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4647 int nbOf2DCells=getNumberOfCells();
4648 int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4649 MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4650 const int *conn=_nodal_connec->getConstPointer();
4651 const int *connI=_nodal_connec_index->getConstPointer();
4652 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4653 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4654 newConnI->alloc(nbOf3DCells+1,1);
4655 int *newConnIPtr=newConnI->getPointer();
4657 std::vector<int> newc;
4658 for(int j=0;j<nbOf2DCells;j++)
4660 AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4661 *newConnIPtr++=(int)newc.size();
4663 newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4664 int *newConnPtr=newConn->getPointer();
4665 int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4666 newConnIPtr=newConnI->getPointer();
4667 for(int iz=0;iz<nbOf1DCells;iz++)
4670 std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4671 for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4673 int icell=(int)(iter-newc.begin());
4674 if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4677 *newConnPtr=(*iter)+iz*deltaPerLev;
4682 *newConnPtr=(*iter);
4685 ret->setConnectivity(newConn,newConnI,true);
4686 ret->setCoords(getCoords());
4691 * Checks if \a this mesh is constituted by only quadratic cells.
4692 * \return bool - \c true if there are only quadratic cells in \a this mesh.
4693 * \throw If the coordinates array is not set.
4694 * \throw If the nodal connectivity of cells is not defined.
4696 bool MEDCouplingUMesh::isFullyQuadratic() const
4698 checkFullyDefined();
4700 int nbOfCells=getNumberOfCells();
4701 for(int i=0;i<nbOfCells && ret;i++)
4703 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4704 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4705 ret=cm.isQuadratic();
4711 * Checks if \a this mesh includes any quadratic cell.
4712 * \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4713 * \throw If the coordinates array is not set.
4714 * \throw If the nodal connectivity of cells is not defined.
4716 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4718 checkFullyDefined();
4720 int nbOfCells=getNumberOfCells();
4721 for(int i=0;i<nbOfCells && !ret;i++)
4723 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4724 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4725 ret=cm.isQuadratic();
4731 * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4732 * this mesh, it remains unchanged.
4733 * \throw If the coordinates array is not set.
4734 * \throw If the nodal connectivity of cells is not defined.
4736 void MEDCouplingUMesh::convertQuadraticCellsToLinear() throw(INTERP_KERNEL::Exception)
4738 checkFullyDefined();
4739 int nbOfCells=getNumberOfCells();
4741 const int *iciptr=_nodal_connec_index->getConstPointer();
4742 for(int i=0;i<nbOfCells;i++)
4744 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4745 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4746 if(cm.isQuadratic())
4748 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4749 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4750 if(!cml.isDynamic())
4751 delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4753 delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4758 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4759 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4760 const int *icptr=_nodal_connec->getConstPointer();
4761 newConn->alloc(getMeshLength()-delta,1);
4762 newConnI->alloc(nbOfCells+1,1);
4763 int *ocptr=newConn->getPointer();
4764 int *ociptr=newConnI->getPointer();
4767 for(int i=0;i<nbOfCells;i++,ociptr++)
4769 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4770 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4771 if(!cm.isQuadratic())
4773 _types.insert(type);
4774 ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4775 ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4779 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4780 _types.insert(typel);
4781 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4782 int newNbOfNodes=cml.getNumberOfNodes();
4784 newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4785 *ocptr++=(int)typel;
4786 ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4787 ociptr[1]=ociptr[0]+newNbOfNodes+1;
4790 setConnectivity(newConn,newConnI,false);
4794 * This method converts all linear cell in \a this to quadratic one.
4795 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4796 * 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)
4797 * 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.
4798 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4799 * end of the existing coordinates.
4801 * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4802 * corresponding quadratic cells. 1 is those creating the 'most' complex.
4803 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4805 * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4807 * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4809 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType) throw(INTERP_KERNEL::Exception)
4811 DataArrayInt *conn=0,*connI=0;
4812 DataArrayDouble *coords=0;
4813 std::set<INTERP_KERNEL::NormalizedCellType> types;
4814 checkFullyDefined();
4815 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
4816 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
4817 int meshDim=getMeshDimension();
4818 switch(conversionType)
4824 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4825 connSafe=conn; connISafe=connI; coordsSafe=coords;
4828 ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4829 connSafe=conn; connISafe=connI; coordsSafe=coords;
4832 ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
4833 connSafe=conn; connISafe=connI; coordsSafe=coords;
4836 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
4844 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
4845 connSafe=conn; connISafe=connI; coordsSafe=coords;
4848 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
4849 connSafe=conn; connISafe=connI; coordsSafe=coords;
4852 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
4853 connSafe=conn; connISafe=connI; coordsSafe=coords;
4856 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
4861 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
4863 setConnectivity(connSafe,connISafe,false);
4865 setCoords(coordsSafe);
4870 * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4871 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4872 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4874 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4876 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4877 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4878 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4879 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4880 int nbOfCells=getNumberOfCells();
4881 int nbOfNodes=getNumberOfNodes();
4882 const int *cPtr=_nodal_connec->getConstPointer();
4883 const int *icPtr=_nodal_connec_index->getConstPointer();
4884 int lastVal=0,offset=nbOfNodes;
4885 for(int i=0;i<nbOfCells;i++,icPtr++)
4887 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4888 if(type==INTERP_KERNEL::NORM_SEG2)
4890 types.insert(INTERP_KERNEL::NORM_SEG3);
4891 newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
4892 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
4893 newConn->pushBackSilent(offset++);
4895 newConnI->pushBackSilent(lastVal);
4896 ret->pushBackSilent(i);
4901 lastVal+=(icPtr[1]-icPtr[0]);
4902 newConnI->pushBackSilent(lastVal);
4903 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4906 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
4907 coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
4911 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 throw(INTERP_KERNEL::Exception)
4913 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4914 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4915 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4917 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4918 DataArrayInt *conn1D=0,*conn1DI=0;
4919 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4920 DataArrayDouble *coordsTmp=0;
4921 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4922 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4923 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4924 const int *c1DPtr=conn1D->begin();
4925 const int *c1DIPtr=conn1DI->begin();
4926 int nbOfCells=getNumberOfCells();
4927 const int *cPtr=_nodal_connec->getConstPointer();
4928 const int *icPtr=_nodal_connec_index->getConstPointer();
4930 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
4932 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4933 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4934 if(!cm.isQuadratic())
4936 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
4937 types.insert(typ2); newConn->pushBackSilent(typ2);
4938 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
4939 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
4940 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
4941 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
4942 newConnI->pushBackSilent(lastVal);
4943 ret->pushBackSilent(i);
4948 lastVal+=(icPtr[1]-icPtr[0]);
4949 newConnI->pushBackSilent(lastVal);
4950 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4953 conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
4958 * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4959 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4960 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4962 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4965 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4966 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4967 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
4970 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4972 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4973 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4975 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4976 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4977 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4979 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4980 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4981 DataArrayInt *conn1D=0,*conn1DI=0;
4982 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4983 DataArrayDouble *coordsTmp=0;
4984 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4985 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4986 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4987 const int *c1DPtr=conn1D->begin();
4988 const int *c1DIPtr=conn1DI->begin();
4989 int nbOfCells=getNumberOfCells();
4990 const int *cPtr=_nodal_connec->getConstPointer();
4991 const int *icPtr=_nodal_connec_index->getConstPointer();
4992 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
4993 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
4995 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4996 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4997 if(!cm.isQuadratic())
4999 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5000 types.insert(typ2); newConn->pushBackSilent(typ2);
5001 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5002 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5003 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5004 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5005 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5006 newConnI->pushBackSilent(lastVal);
5007 ret->pushBackSilent(i);
5012 lastVal+=(icPtr[1]-icPtr[0]);
5013 newConnI->pushBackSilent(lastVal);
5014 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5017 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5018 coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5023 * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5024 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5025 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5027 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5029 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5030 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5031 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5034 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5036 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5037 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5038 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5039 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5041 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5042 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5043 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5045 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5046 const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5047 DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5048 std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5049 DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5050 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5051 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5052 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5053 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5054 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5055 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5056 const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5057 int nbOfCells=getNumberOfCells();
5058 const int *cPtr=_nodal_connec->getConstPointer();
5059 const int *icPtr=_nodal_connec_index->getConstPointer();
5060 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5061 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5063 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5064 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5065 if(!cm.isQuadratic())
5067 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5068 if(typ2==INTERP_KERNEL::NORM_ERROR)
5070 std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5071 throw INTERP_KERNEL::Exception(oss.str().c_str());
5073 types.insert(typ2); newConn->pushBackSilent(typ2);
5074 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5075 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5076 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5077 for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5079 int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5080 int tmpPos=newConn->getNumberOfTuples();
5081 newConn->pushBackSilent(nodeId2);
5082 ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5084 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5085 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5086 newConnI->pushBackSilent(lastVal);
5087 ret->pushBackSilent(i);
5092 lastVal+=(icPtr[1]-icPtr[0]);
5093 newConnI->pushBackSilent(lastVal);
5094 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5097 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5098 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5099 coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5100 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5101 std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5102 int *c=newConn->getPointer();
5103 const int *cI(newConnI->begin());
5104 for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5105 c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5106 offset=coordsTmp2Safe->getNumberOfTuples();
5107 for(const int *elt=ret->begin();elt!=ret->end();elt++)
5108 c[cI[(*elt)+1]-1]+=offset;
5109 coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5114 * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5115 * so that the number of cells remains the same. Quadratic faces are converted to
5116 * polygons. This method works only for 2D meshes in
5117 * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5118 * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5119 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5120 * \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5121 * a polylinized edge constituting the input polygon.
5122 * \throw If the coordinates array is not set.
5123 * \throw If the nodal connectivity of cells is not defined.
5124 * \throw If \a this->getMeshDimension() != 2.
5125 * \throw If \a this->getSpaceDimension() != 2.
5127 void MEDCouplingUMesh::tessellate2D(double eps) throw(INTERP_KERNEL::Exception)
5129 checkFullyDefined();
5130 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
5131 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5132 double epsa=fabs(eps);
5133 if(epsa<std::numeric_limits<double>::min())
5134 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 !");
5135 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5136 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5137 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5138 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5139 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5140 revDesc1=0; revDescIndx1=0;
5141 mDesc->tessellate2DCurve(eps);
5142 subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5143 setCoords(mDesc->getCoords());
5147 * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5148 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5149 * \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5150 * a sub-divided edge.
5151 * \throw If the coordinates array is not set.
5152 * \throw If the nodal connectivity of cells is not defined.
5153 * \throw If \a this->getMeshDimension() != 1.
5154 * \throw If \a this->getSpaceDimension() != 2.
5156 void MEDCouplingUMesh::tessellate2DCurve(double eps) throw(INTERP_KERNEL::Exception)
5158 checkFullyDefined();
5159 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5160 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5161 double epsa=fabs(eps);
5162 if(epsa<std::numeric_limits<double>::min())
5163 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 !");
5164 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5165 int nbCells=getNumberOfCells();
5166 int nbNodes=getNumberOfNodes();
5167 const int *conn=_nodal_connec->getConstPointer();
5168 const int *connI=_nodal_connec_index->getConstPointer();
5169 const double *coords=_coords->getConstPointer();
5170 std::vector<double> addCoo;
5171 std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5172 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5173 newConnI->alloc(nbCells+1,1);
5174 int *newConnIPtr=newConnI->getPointer();
5177 INTERP_KERNEL::Node *tmp2[3];
5178 std::set<INTERP_KERNEL::NormalizedCellType> types;
5179 for(int i=0;i<nbCells;i++,newConnIPtr++)
5181 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5182 if(cm.isQuadratic())
5183 {//assert(connI[i+1]-connI[i]-1==3)
5184 tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5185 tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5186 tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5187 tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5188 INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5191 eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5192 types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5194 newConnIPtr[1]=(int)newConn.size();
5198 types.insert(INTERP_KERNEL::NORM_SEG2);
5199 newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5200 newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5201 newConnIPtr[1]=newConnIPtr[0]+3;
5206 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5207 newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5208 newConnIPtr[1]=newConnIPtr[0]+3;
5211 if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tasselation : no update needed
5214 DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5215 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5216 newConnArr->alloc((int)newConn.size(),1);
5217 std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5218 DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5219 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5220 newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5221 double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5222 std::copy(addCoo.begin(),addCoo.end(),work);
5223 DataArrayDouble::SetArrayIn(newCoords,_coords);
5228 * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5229 * In addition, returns an array mapping new cells to old ones. <br>
5230 * This method typically increases the number of cells in \a this mesh
5231 * but the number of nodes remains \b unchanged.
5232 * That's why the 3D splitting policies
5233 * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5234 * \param [in] policy - specifies a pattern used for splitting.
5235 * The semantic of \a policy is:
5236 * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5237 * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5238 * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8 into 5 TETRA4 (for 3D mesh only).
5239 * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8 into 6 TETRA4 (for 3D mesh only).
5240 * \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5241 * an id of old cell producing it. The caller is to delete this array using
5242 * decrRef() as it is no more needed.
5243 * \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5244 * \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5245 * and \a this->getMeshDimension() != 3.
5246 * \throw If \a policy is not one of the four discussed above.
5247 * \throw If the nodal connectivity of cells is not defined.
5249 DataArrayInt *MEDCouplingUMesh::simplexize(int policy) throw(INTERP_KERNEL::Exception)
5254 return simplexizePol0();
5256 return simplexizePol1();
5257 case (int) INTERP_KERNEL::PLANAR_FACE_5:
5258 return simplexizePlanarFace5();
5259 case (int) INTERP_KERNEL::PLANAR_FACE_6:
5260 return simplexizePlanarFace6();
5262 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)");
5267 * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5268 * - 1D: INTERP_KERNEL::NORM_SEG2
5269 * - 2D: INTERP_KERNEL::NORM_TRI3
5270 * - 3D: INTERP_KERNEL::NORM_TETRA4.
5272 * This method is useful for users that need to use P1 field services as
5273 * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5274 * All these methods need mesh support containing only simplex cells.
5275 * \return bool - \c true if there are only simplex cells in \a this mesh.
5276 * \throw If the coordinates array is not set.
5277 * \throw If the nodal connectivity of cells is not defined.
5278 * \throw If \a this->getMeshDimension() < 1.
5280 bool MEDCouplingUMesh::areOnlySimplexCells() const throw(INTERP_KERNEL::Exception)
5282 checkFullyDefined();
5283 int mdim=getMeshDimension();
5284 if(mdim<1 || mdim>3)
5285 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5286 int nbCells=getNumberOfCells();
5287 const int *conn=_nodal_connec->getConstPointer();
5288 const int *connI=_nodal_connec_index->getConstPointer();
5289 for(int i=0;i<nbCells;i++)
5291 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5299 * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5301 DataArrayInt *MEDCouplingUMesh::simplexizePol0() throw(INTERP_KERNEL::Exception)
5303 checkConnectivityFullyDefined();
5304 if(getMeshDimension()!=2)
5305 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5306 int nbOfCells=getNumberOfCells();
5307 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5308 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5309 ret->alloc(nbOfCells+nbOfCutCells,1);
5310 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5311 int *retPt=ret->getPointer();
5312 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5313 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5314 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5315 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5316 int *pt=newConn->getPointer();
5317 int *ptI=newConnI->getPointer();
5319 const int *oldc=_nodal_connec->getConstPointer();
5320 const int *ci=_nodal_connec_index->getConstPointer();
5321 for(int i=0;i<nbOfCells;i++,ci++)
5323 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5325 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5326 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5327 pt=std::copy(tmp,tmp+8,pt);
5336 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5337 ptI[1]=ptI[0]+ci[1]-ci[0];
5342 _nodal_connec->decrRef();
5343 _nodal_connec=newConn.retn();
5344 _nodal_connec_index->decrRef();
5345 _nodal_connec_index=newConnI.retn();
5352 * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5354 DataArrayInt *MEDCouplingUMesh::simplexizePol1() throw(INTERP_KERNEL::Exception)
5356 checkConnectivityFullyDefined();
5357 if(getMeshDimension()!=2)
5358 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5359 int nbOfCells=getNumberOfCells();
5360 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5361 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5362 ret->alloc(nbOfCells+nbOfCutCells,1);
5363 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5364 int *retPt=ret->getPointer();
5365 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5366 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5367 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5368 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5369 int *pt=newConn->getPointer();
5370 int *ptI=newConnI->getPointer();
5372 const int *oldc=_nodal_connec->getConstPointer();
5373 const int *ci=_nodal_connec_index->getConstPointer();
5374 for(int i=0;i<nbOfCells;i++,ci++)
5376 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5378 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5379 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5380 pt=std::copy(tmp,tmp+8,pt);
5389 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5390 ptI[1]=ptI[0]+ci[1]-ci[0];
5395 _nodal_connec->decrRef();
5396 _nodal_connec=newConn.retn();
5397 _nodal_connec_index->decrRef();
5398 _nodal_connec_index=newConnI.retn();
5405 * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5407 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5() throw(INTERP_KERNEL::Exception)
5409 checkConnectivityFullyDefined();
5410 if(getMeshDimension()!=3)
5411 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5412 int nbOfCells=getNumberOfCells();
5413 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5414 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5415 ret->alloc(nbOfCells+4*nbOfCutCells,1);
5416 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5417 int *retPt=ret->getPointer();
5418 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5419 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5420 newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5421 newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5422 int *pt=newConn->getPointer();
5423 int *ptI=newConnI->getPointer();
5425 const int *oldc=_nodal_connec->getConstPointer();
5426 const int *ci=_nodal_connec_index->getConstPointer();
5427 for(int i=0;i<nbOfCells;i++,ci++)
5429 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5431 for(int j=0;j<5;j++,pt+=5,ptI++)
5433 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5434 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];
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 INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5459 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6() throw(INTERP_KERNEL::Exception)
5461 checkConnectivityFullyDefined();
5462 if(getMeshDimension()!=3)
5463 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5464 int nbOfCells=getNumberOfCells();
5465 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5466 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5467 ret->alloc(nbOfCells+5*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+5*nbOfCutCells+1,1);
5473 newConn->alloc(getMeshLength()+21*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_HEXA8)
5483 for(int j=0;j<6;j++,pt+=5,ptI++)
5485 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5486 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];
5493 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5494 ptI[1]=ptI[0]+ci[1]-ci[0];
5499 _nodal_connec->decrRef();
5500 _nodal_connec=newConn.retn();
5501 _nodal_connec_index->decrRef();
5502 _nodal_connec_index=newConnI.retn();
5509 * 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.
5510 * This method completly ignore coordinates.
5511 * \param nodeSubdived is the nodal connectivity of subdivision of edges
5512 * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5513 * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5514 * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5516 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex) throw(INTERP_KERNEL::Exception)
5518 checkFullyDefined();
5519 if(getMeshDimension()!=2)
5520 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5521 int nbOfCells=getNumberOfCells();
5522 int *connI=_nodal_connec_index->getPointer();
5524 for(int i=0;i<nbOfCells;i++,connI++)
5526 int offset=descIndex[i];
5527 int nbOfEdges=descIndex[i+1]-offset;
5529 bool ddirect=desc[offset+nbOfEdges-1]>0;
5530 int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5531 int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5532 for(int j=0;j<nbOfEdges;j++)
5534 bool direct=desc[offset+j]>0;
5535 int edgeId=std::abs(desc[offset+j])-1;
5536 if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5538 int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5539 int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5540 int ref2=direct?id1:id2;
5543 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5544 newConnLgth+=nbOfSubNodes-1;
5549 std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5550 throw INTERP_KERNEL::Exception(oss.str().c_str());
5555 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5558 newConnLgth++;//+1 is for cell type
5559 connI[1]=newConnLgth;
5562 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5563 newConn->alloc(newConnLgth,1);
5564 int *work=newConn->getPointer();
5565 for(int i=0;i<nbOfCells;i++)
5567 *work++=INTERP_KERNEL::NORM_POLYGON;
5568 int offset=descIndex[i];
5569 int nbOfEdges=descIndex[i+1]-offset;
5570 for(int j=0;j<nbOfEdges;j++)
5572 bool direct=desc[offset+j]>0;
5573 int edgeId=std::abs(desc[offset+j])-1;
5575 work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5578 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5579 std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5580 work=std::copy(it,it+nbOfSubNodes-1,work);
5584 DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5587 _types.insert(INTERP_KERNEL::NORM_POLYGON);
5591 * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5592 * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5593 * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5594 * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5595 * so it can be useful to call mergeNodes() before calling this method.
5596 * \throw If \a this->getMeshDimension() <= 1.
5597 * \throw If the coordinates array is not set.
5598 * \throw If the nodal connectivity of cells is not defined.
5600 void MEDCouplingUMesh::convertDegeneratedCells() throw(INTERP_KERNEL::Exception)
5602 checkFullyDefined();
5603 if(getMeshDimension()<=1)
5604 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5605 int nbOfCells=getNumberOfCells();
5608 int initMeshLgth=getMeshLength();
5609 int *conn=_nodal_connec->getPointer();
5610 int *index=_nodal_connec_index->getPointer();
5614 for(int i=0;i<nbOfCells;i++)
5616 lgthOfCurCell=index[i+1]-posOfCurCell;
5617 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5619 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5620 conn+newPos+1,newLgth);
5621 conn[newPos]=newType;
5623 posOfCurCell=index[i+1];
5626 if(newPos!=initMeshLgth)
5627 _nodal_connec->reAlloc(newPos);
5632 * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5633 * A cell is considered to be oriented correctly if an angle between its
5634 * normal vector and a given vector is less than \c PI / \c 2.
5635 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5637 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5639 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5640 * is not cleared before filling in.
5641 * \throw If \a this->getMeshDimension() != 2.
5642 * \throw If \a this->getSpaceDimension() != 3.
5644 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5645 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5647 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5649 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5650 throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5651 int nbOfCells=getNumberOfCells();
5652 const int *conn=_nodal_connec->getConstPointer();
5653 const int *connI=_nodal_connec_index->getConstPointer();
5654 const double *coordsPtr=_coords->getConstPointer();
5655 for(int i=0;i<nbOfCells;i++)
5657 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5658 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5660 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5661 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5668 * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5669 * considered to be oriented correctly if an angle between its normal vector and a
5670 * given vector is less than \c PI / \c 2.
5671 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5673 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5675 * \throw If \a this->getMeshDimension() != 2.
5676 * \throw If \a this->getSpaceDimension() != 3.
5678 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5679 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5681 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly) throw(INTERP_KERNEL::Exception)
5683 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5684 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5685 int nbOfCells=getNumberOfCells();
5686 int *conn=_nodal_connec->getPointer();
5687 const int *connI=_nodal_connec_index->getConstPointer();
5688 const double *coordsPtr=_coords->getConstPointer();
5689 bool isModified=false;
5690 for(int i=0;i<nbOfCells;i++)
5692 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5693 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5695 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5696 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5699 std::vector<int> tmp(connI[i+1]-connI[i]-2);
5700 std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5701 std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5706 _nodal_connec->declareAsNew();
5711 * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5712 * oriented facets. The normal vector of the facet should point out of the cell.
5713 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5714 * is not cleared before filling in.
5715 * \throw If \a this->getMeshDimension() != 3.
5716 * \throw If \a this->getSpaceDimension() != 3.
5717 * \throw If the coordinates array is not set.
5718 * \throw If the nodal connectivity of cells is not defined.
5720 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5721 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5723 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5725 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5726 throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5727 int nbOfCells=getNumberOfCells();
5728 const int *conn=_nodal_connec->getConstPointer();
5729 const int *connI=_nodal_connec_index->getConstPointer();
5730 const double *coordsPtr=_coords->getConstPointer();
5731 for(int i=0;i<nbOfCells;i++)
5733 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5734 if(type==INTERP_KERNEL::NORM_POLYHED)
5736 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5743 * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
5745 * \throw If \a this->getMeshDimension() != 3.
5746 * \throw If \a this->getSpaceDimension() != 3.
5747 * \throw If the coordinates array is not set.
5748 * \throw If the nodal connectivity of cells is not defined.
5749 * \throw If the reparation fails.
5751 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5752 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5753 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5755 void MEDCouplingUMesh::orientCorrectlyPolyhedrons() throw(INTERP_KERNEL::Exception)
5757 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5758 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
5759 int nbOfCells=getNumberOfCells();
5760 int *conn=_nodal_connec->getPointer();
5761 const int *connI=_nodal_connec_index->getConstPointer();
5762 const double *coordsPtr=_coords->getConstPointer();
5763 for(int i=0;i<nbOfCells;i++)
5765 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5766 if(type==INTERP_KERNEL::NORM_POLYHED)
5770 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5771 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5773 catch(INTERP_KERNEL::Exception& e)
5775 std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
5776 throw INTERP_KERNEL::Exception(oss.str().c_str());
5784 * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
5785 * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
5786 * according to which the first facet of the cell should be oriented to have the normal vector
5787 * pointing out of cell.
5788 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
5789 * cells. The caller is to delete this array using decrRef() as it is no more
5791 * \throw If \a this->getMeshDimension() != 3.
5792 * \throw If \a this->getSpaceDimension() != 3.
5793 * \throw If the coordinates array is not set.
5794 * \throw If the nodal connectivity of cells is not defined.
5796 * \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
5797 * \ref py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
5798 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5800 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells() throw(INTERP_KERNEL::Exception)
5802 const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
5803 if(getMeshDimension()!=3)
5804 throw INTERP_KERNEL::Exception(msg);
5805 int spaceDim=getSpaceDimension();
5807 throw INTERP_KERNEL::Exception(msg);
5809 int nbOfCells=getNumberOfCells();
5810 int *conn=_nodal_connec->getPointer();
5811 const int *connI=_nodal_connec_index->getConstPointer();
5812 const double *coo=getCoords()->getConstPointer();
5813 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
5814 for(int i=0;i<nbOfCells;i++)
5816 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5817 if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
5819 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
5821 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5822 cells->pushBackSilent(i);
5826 return cells.retn();
5830 * This method is a faster method to correct orientation of all 3D cells in \a this.
5831 * 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.
5832 * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
5834 * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
5835 * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons,
5837 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells() throw(INTERP_KERNEL::Exception)
5839 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5840 throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
5841 int nbOfCells=getNumberOfCells();
5842 int *conn=_nodal_connec->getPointer();
5843 const int *connI=_nodal_connec_index->getConstPointer();
5844 const double *coordsPtr=_coords->getConstPointer();
5845 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5846 for(int i=0;i<nbOfCells;i++)
5848 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5851 case INTERP_KERNEL::NORM_TETRA4:
5853 if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5855 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
5856 ret->pushBackSilent(i);
5860 case INTERP_KERNEL::NORM_PYRA5:
5862 if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5864 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
5865 ret->pushBackSilent(i);
5869 case INTERP_KERNEL::NORM_PENTA6:
5870 case INTERP_KERNEL::NORM_HEXA8:
5871 case INTERP_KERNEL::NORM_HEXGP12:
5873 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5875 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5876 ret->pushBackSilent(i);
5880 case INTERP_KERNEL::NORM_POLYHED:
5882 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5884 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5885 ret->pushBackSilent(i);
5890 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 !");
5898 * This method has a sense for meshes with spaceDim==3 and meshDim==2.
5899 * If it is not the case an exception will be thrown.
5900 * This method is fast because the first cell of \a this is used to compute the plane.
5901 * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
5902 * \param pos output of size at least 3 used to store a point owned of searched plane.
5904 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const throw(INTERP_KERNEL::Exception)
5906 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5907 throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
5908 const int *conn=_nodal_connec->getConstPointer();
5909 const int *connI=_nodal_connec_index->getConstPointer();
5910 const double *coordsPtr=_coords->getConstPointer();
5911 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
5912 std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
5916 * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
5917 * cells. Currently cells of the following types are treated:
5918 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5919 * For a cell of other type an exception is thrown.
5920 * Space dimension of a 2D mesh can be either 2 or 3.
5921 * The Edge Ratio of a cell \f$t\f$ is:
5922 * \f$\frac{|t|_\infty}{|t|_0}\f$,
5923 * where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
5924 * the smallest edge lengths of \f$t\f$.
5925 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5926 * cells and one time, lying on \a this mesh. The caller is to delete this
5927 * field using decrRef() as it is no more needed.
5928 * \throw If the coordinates array is not set.
5929 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5930 * \throw If the connectivity data array has more than one component.
5931 * \throw If the connectivity data array has a named component.
5932 * \throw If the connectivity index data array has more than one component.
5933 * \throw If the connectivity index data array has a named component.
5934 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
5935 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
5936 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
5938 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const throw(INTERP_KERNEL::Exception)
5941 int spaceDim=getSpaceDimension();
5942 int meshDim=getMeshDimension();
5943 if(spaceDim!=2 && spaceDim!=3)
5944 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
5945 if(meshDim!=2 && meshDim!=3)
5946 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
5947 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5949 int nbOfCells=getNumberOfCells();
5950 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5951 arr->alloc(nbOfCells,1);
5952 double *pt=arr->getPointer();
5953 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5954 const int *conn=_nodal_connec->getConstPointer();
5955 const int *connI=_nodal_connec_index->getConstPointer();
5956 const double *coo=_coords->getConstPointer();
5958 for(int i=0;i<nbOfCells;i++,pt++)
5960 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5963 case INTERP_KERNEL::NORM_TRI3:
5965 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5966 *pt=INTERP_KERNEL::triEdgeRatio(tmp);
5969 case INTERP_KERNEL::NORM_QUAD4:
5971 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5972 *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
5975 case INTERP_KERNEL::NORM_TETRA4:
5977 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5978 *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
5982 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
5984 conn+=connI[i+1]-connI[i];
5986 ret->setName("EdgeRatio");
5987 ret->synchronizeTimeWithSupport();
5992 * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
5993 * cells. Currently cells of the following types are treated:
5994 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5995 * For a cell of other type an exception is thrown.
5996 * Space dimension of a 2D mesh can be either 2 or 3.
5997 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5998 * cells and one time, lying on \a this mesh. The caller is to delete this
5999 * field using decrRef() as it is no more needed.
6000 * \throw If the coordinates array is not set.
6001 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6002 * \throw If the connectivity data array has more than one component.
6003 * \throw If the connectivity data array has a named component.
6004 * \throw If the connectivity index data array has more than one component.
6005 * \throw If the connectivity index data array has a named component.
6006 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6007 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6008 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6010 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const throw(INTERP_KERNEL::Exception)
6013 int spaceDim=getSpaceDimension();
6014 int meshDim=getMeshDimension();
6015 if(spaceDim!=2 && spaceDim!=3)
6016 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6017 if(meshDim!=2 && meshDim!=3)
6018 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6019 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6021 int nbOfCells=getNumberOfCells();
6022 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6023 arr->alloc(nbOfCells,1);
6024 double *pt=arr->getPointer();
6025 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6026 const int *conn=_nodal_connec->getConstPointer();
6027 const int *connI=_nodal_connec_index->getConstPointer();
6028 const double *coo=_coords->getConstPointer();
6030 for(int i=0;i<nbOfCells;i++,pt++)
6032 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6035 case INTERP_KERNEL::NORM_TRI3:
6037 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6038 *pt=INTERP_KERNEL::triAspectRatio(tmp);
6041 case INTERP_KERNEL::NORM_QUAD4:
6043 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6044 *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6047 case INTERP_KERNEL::NORM_TETRA4:
6049 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6050 *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6054 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6056 conn+=connI[i+1]-connI[i];
6058 ret->setName("AspectRatio");
6059 ret->synchronizeTimeWithSupport();
6064 * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6065 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6066 * treated: INTERP_KERNEL::NORM_QUAD4.
6067 * For a cell of other type an exception is thrown.
6068 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6069 * cells and one time, lying on \a this mesh. The caller is to delete this
6070 * field using decrRef() as it is no more needed.
6071 * \throw If the coordinates array is not set.
6072 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6073 * \throw If the connectivity data array has more than one component.
6074 * \throw If the connectivity data array has a named component.
6075 * \throw If the connectivity index data array has more than one component.
6076 * \throw If the connectivity index data array has a named component.
6077 * \throw If \a this->getMeshDimension() != 2.
6078 * \throw If \a this->getSpaceDimension() != 3.
6079 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6081 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const throw(INTERP_KERNEL::Exception)
6084 int spaceDim=getSpaceDimension();
6085 int meshDim=getMeshDimension();
6087 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6089 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6090 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6092 int nbOfCells=getNumberOfCells();
6093 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6094 arr->alloc(nbOfCells,1);
6095 double *pt=arr->getPointer();
6096 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6097 const int *conn=_nodal_connec->getConstPointer();
6098 const int *connI=_nodal_connec_index->getConstPointer();
6099 const double *coo=_coords->getConstPointer();
6101 for(int i=0;i<nbOfCells;i++,pt++)
6103 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6106 case INTERP_KERNEL::NORM_QUAD4:
6108 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6109 *pt=INTERP_KERNEL::quadWarp(tmp);
6113 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6115 conn+=connI[i+1]-connI[i];
6117 ret->setName("Warp");
6118 ret->synchronizeTimeWithSupport();
6124 * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6125 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6126 * treated: INTERP_KERNEL::NORM_QUAD4.
6127 * For a cell of other type an exception is thrown.
6128 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6129 * cells and one time, lying on \a this mesh. The caller is to delete this
6130 * field using decrRef() as it is no more needed.
6131 * \throw If the coordinates array is not set.
6132 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6133 * \throw If the connectivity data array has more than one component.
6134 * \throw If the connectivity data array has a named component.
6135 * \throw If the connectivity index data array has more than one component.
6136 * \throw If the connectivity index data array has a named component.
6137 * \throw If \a this->getMeshDimension() != 2.
6138 * \throw If \a this->getSpaceDimension() != 3.
6139 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6141 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const throw(INTERP_KERNEL::Exception)
6144 int spaceDim=getSpaceDimension();
6145 int meshDim=getMeshDimension();
6147 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6149 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6150 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6152 int nbOfCells=getNumberOfCells();
6153 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6154 arr->alloc(nbOfCells,1);
6155 double *pt=arr->getPointer();
6156 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6157 const int *conn=_nodal_connec->getConstPointer();
6158 const int *connI=_nodal_connec_index->getConstPointer();
6159 const double *coo=_coords->getConstPointer();
6161 for(int i=0;i<nbOfCells;i++,pt++)
6163 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6166 case INTERP_KERNEL::NORM_QUAD4:
6168 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6169 *pt=INTERP_KERNEL::quadSkew(tmp);
6173 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6175 conn+=connI[i+1]-connI[i];
6177 ret->setName("Skew");
6178 ret->synchronizeTimeWithSupport();
6183 * This method aggregate the bbox of each cell and put it into bbox parameter.
6184 * \param bbox out parameter of size 2*spacedim*nbOfcells.
6186 void MEDCouplingUMesh::getBoundingBoxForBBTree(std::vector<double>& bbox) const
6188 int spaceDim=getSpaceDimension();
6189 int nbOfCells=getNumberOfCells();
6190 bbox.resize(2*nbOfCells*spaceDim);
6191 for(int i=0;i<nbOfCells*spaceDim;i++)
6193 bbox[2*i]=std::numeric_limits<double>::max();
6194 bbox[2*i+1]=-std::numeric_limits<double>::max();
6196 const double *coordsPtr=_coords->getConstPointer();
6197 const int *conn=_nodal_connec->getConstPointer();
6198 const int *connI=_nodal_connec_index->getConstPointer();
6199 for(int i=0;i<nbOfCells;i++)
6201 int offset=connI[i]+1;
6202 int nbOfNodesForCell=connI[i+1]-offset;
6203 for(int j=0;j<nbOfNodesForCell;j++)
6205 int nodeId=conn[offset+j];
6207 for(int k=0;k<spaceDim;k++)
6209 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6210 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6218 namespace ParaMEDMEMImpl
6223 ConnReader(const int *c, int val):_conn(c),_val(val) { }
6224 bool operator() (const int& pos) { return _conn[pos]!=_val; }
6233 ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6234 bool operator() (const int& pos) { return _conn[pos]==_val; }
6244 * This method expects that \a this is sorted by types. If not an exception will be thrown.
6245 * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6246 * \a this is composed in cell types.
6247 * The returned array is of size 3*n where n is the number of different types present in \a this.
6248 * For every k in [0,n] ret[3*k+2]==0 because it has no sense here.
6249 * This parameter is kept only for compatibility with other methode listed above.
6251 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const throw(INTERP_KERNEL::Exception)
6253 checkConnectivityFullyDefined();
6254 const int *conn=_nodal_connec->getConstPointer();
6255 const int *connI=_nodal_connec_index->getConstPointer();
6256 const int *work=connI;
6257 int nbOfCells=getNumberOfCells();
6258 std::size_t n=getAllTypes().size();
6259 std::vector<int> ret(3*n,0); //ret[3*k+2]==0 because it has no sense here
6260 std::set<INTERP_KERNEL::NormalizedCellType> types;
6261 for(std::size_t i=0;work!=connI+nbOfCells;i++)
6263 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6264 if(types.find(typ)!=types.end())
6266 std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6267 oss << " is not contiguous !";
6268 throw INTERP_KERNEL::Exception(oss.str().c_str());
6272 const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6273 ret[3*i+1]=(int)std::distance(work,work2);
6280 * This method is used to check that this has contiguous cell type in same order than described in \a code.
6281 * only for types cell, type node is not managed.
6282 * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6283 * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6284 * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6285 * If 2 or more same geometric type is in \a code and exception is thrown too.
6287 * This method firstly checks
6288 * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6289 * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6290 * an exception is thrown too.
6292 * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6293 * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown
6294 * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6296 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6299 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6300 std::size_t sz=code.size();
6303 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6304 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6306 for(std::size_t i=0;i<n;i++)
6307 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6309 types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6311 if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6312 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6315 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6316 if(idsPerType.empty())
6318 if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6319 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6320 if(types.size()==_types.size())
6323 DataArrayInt *ret=DataArrayInt::New();
6325 int *retPtr=ret->getPointer();
6326 const int *connI=_nodal_connec_index->getConstPointer();
6327 const int *conn=_nodal_connec->getConstPointer();
6328 int nbOfCells=getNumberOfCells();
6331 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6333 i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6334 int offset=(int)std::distance(connI,i);
6335 if(code[3*kk+2]==-1)
6337 const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6338 std::size_t pos2=std::distance(i,j);
6339 for(std::size_t k=0;k<pos2;k++)
6340 *retPtr++=(int)k+offset;
6345 retPtr=std::transform(idsPerType[code[3*kk+2]]->getConstPointer(),idsPerType[code[3*kk+2]]->getConstPointer()+idsPerType[code[3*kk+2]]->getNbOfElems(),
6346 retPtr,std::bind2nd(std::plus<int>(),offset));
6353 * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6354 * 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.
6355 * 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.
6356 * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6358 * \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.
6359 * \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,
6360 * \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6361 * \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.
6362 * This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6363 * \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
6365 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6368 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6369 if(profile->getNumberOfComponents()!=1)
6370 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6371 checkConnectivityFullyDefined();
6372 const int *conn=_nodal_connec->getConstPointer();
6373 const int *connI=_nodal_connec_index->getConstPointer();
6374 int nbOfCells=getNumberOfCells();
6375 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6376 std::vector<int> typeRangeVals(1);
6377 for(const int *i=connI;i!=connI+nbOfCells;)
6379 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6380 if(std::find(types.begin(),types.end(),curType)!=types.end())
6382 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6384 types.push_back(curType);
6385 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6386 typeRangeVals.push_back((int)std::distance(connI,i));
6389 DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6390 profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6391 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6392 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6393 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6395 int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6396 code.resize(3*nbOfCastsFinal);
6397 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6398 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6399 for(int i=0;i<nbOfCastsFinal;i++)
6401 int castId=castsPresent->getIJ(i,0);
6402 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6403 idsInPflPerType2.push_back(tmp3);
6404 code[3*i]=(int)types[castId];
6405 code[3*i+1]=tmp3->getNumberOfTuples();
6406 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6407 if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6409 tmp4->copyStringInfoFrom(*profile);
6410 idsPerType2.push_back(tmp4);
6411 code[3*i+2]=(int)idsPerType2.size()-1;
6418 std::size_t sz2=idsInPflPerType2.size();
6419 idsInPflPerType.resize(sz2);
6420 for(std::size_t i=0;i<sz2;i++)
6422 DataArrayInt *locDa=idsInPflPerType2[i];
6424 idsInPflPerType[i]=locDa;
6426 std::size_t sz=idsPerType2.size();
6427 idsPerType.resize(sz);
6428 for(std::size_t i=0;i<sz;i++)
6430 DataArrayInt *locDa=idsPerType2[i];
6432 idsPerType[i]=locDa;
6437 * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6438 * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6439 * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6440 * 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.
6442 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const throw(INTERP_KERNEL::Exception)
6444 checkFullyDefined();
6445 nM1LevMesh->checkFullyDefined();
6446 if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6447 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6448 if(_coords!=nM1LevMesh->getCoords())
6449 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6450 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6451 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6452 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6453 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6454 desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6455 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6456 tmp->setConnectivity(tmp0,tmp1);
6457 tmp->renumberCells(ret0->getConstPointer(),false);
6458 revDesc=tmp->getNodalConnectivity();
6459 revDescIndx=tmp->getNodalConnectivityIndex();
6460 DataArrayInt *ret=0;
6461 if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6464 ret->getMaxValue(tmp2);
6466 std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6467 throw INTERP_KERNEL::Exception(oss.str().c_str());
6472 revDescIndx->incrRef();
6475 meshnM1Old2New=ret0;
6480 * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6481 * necessary for writing the mesh to MED file. Additionally returns a permutation array
6482 * in "Old to New" mode.
6483 * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6484 * this array using decrRef() as it is no more needed.
6485 * \throw If the nodal connectivity of cells is not defined.
6487 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt() throw(INTERP_KERNEL::Exception)
6489 checkConnectivityFullyDefined();
6490 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6491 renumberCells(ret->getConstPointer(),false);
6496 * This methods checks that cells are sorted by their types.
6497 * This method makes asumption (no check) that connectivity is correctly set before calling.
6499 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6501 checkFullyDefined();
6502 const int *conn=_nodal_connec->getConstPointer();
6503 const int *connI=_nodal_connec_index->getConstPointer();
6504 int nbOfCells=getNumberOfCells();
6505 std::set<INTERP_KERNEL::NormalizedCellType> types;
6506 for(const int *i=connI;i!=connI+nbOfCells;)
6508 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6509 if(types.find(curType)!=types.end())
6511 types.insert(curType);
6512 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6518 * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6519 * The geometric type order is specified by MED file.
6521 * \sa MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6523 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6525 return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6529 * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6530 * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
6531 * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6532 * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6534 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6536 checkFullyDefined();
6537 const int *conn=_nodal_connec->getConstPointer();
6538 const int *connI=_nodal_connec_index->getConstPointer();
6539 int nbOfCells=getNumberOfCells();
6543 std::set<INTERP_KERNEL::NormalizedCellType> sg;
6544 for(const int *i=connI;i!=connI+nbOfCells;)
6546 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6547 const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6548 if(isTypeExists!=orderEnd)
6550 int pos=(int)std::distance(orderBg,isTypeExists);
6554 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6558 if(sg.find(curType)==sg.end())
6560 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6571 * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6572 * 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
6573 * 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'.
6575 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const throw(INTERP_KERNEL::Exception)
6577 checkConnectivityFullyDefined();
6578 int nbOfCells=getNumberOfCells();
6579 const int *conn=_nodal_connec->getConstPointer();
6580 const int *connI=_nodal_connec_index->getConstPointer();
6581 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6582 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6583 tmpa->alloc(nbOfCells,1);
6584 tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6585 tmpb->fillWithZero();
6586 int *tmp=tmpa->getPointer();
6587 int *tmp2=tmpb->getPointer();
6588 for(const int *i=connI;i!=connI+nbOfCells;i++)
6590 const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6593 int pos=(int)std::distance(orderBg,where);
6595 tmp[std::distance(connI,i)]=pos;
6599 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6600 std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6601 oss << " has a type " << cm.getRepr() << " not in input array of type !";
6602 throw INTERP_KERNEL::Exception(oss.str().c_str());
6605 nbPerType=tmpb.retn();
6610 * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
6612 * \return a new object containing the old to new correspondance.
6614 * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6616 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6618 return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6622 * 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.
6623 * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6624 * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6625 * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6627 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const throw(INTERP_KERNEL::Exception)
6629 DataArrayInt *nbPerType=0;
6630 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6631 nbPerType->decrRef();
6632 return tmpa->buildPermArrPerLevel();
6636 * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
6637 * The number of cells remains unchanged after the call of this method.
6638 * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6639 * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6641 * \return the array giving the correspondance old to new.
6643 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6645 checkFullyDefined();
6647 const int *conn=_nodal_connec->getConstPointer();
6648 const int *connI=_nodal_connec_index->getConstPointer();
6649 int nbOfCells=getNumberOfCells();
6650 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6651 for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6652 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6654 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6655 types.push_back(curType);
6656 for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6658 DataArrayInt *ret=DataArrayInt::New();
6659 ret->alloc(nbOfCells,1);
6660 int *retPtr=ret->getPointer();
6661 std::fill(retPtr,retPtr+nbOfCells,-1);
6663 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6665 for(const int *i=connI;i!=connI+nbOfCells;i++)
6666 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6667 retPtr[std::distance(connI,i)]=newCellId++;
6669 renumberCells(retPtr,false);
6674 * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
6675 * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
6676 * This method makes asumption that connectivity is correctly set before calling.
6678 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
6680 checkFullyDefined();
6681 const int *conn=_nodal_connec->getConstPointer();
6682 const int *connI=_nodal_connec_index->getConstPointer();
6683 int nbOfCells=getNumberOfCells();
6684 std::vector<MEDCouplingUMesh *> ret;
6685 for(const int *i=connI;i!=connI+nbOfCells;)
6687 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6688 int beginCellId=(int)std::distance(connI,i);
6689 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6690 int endCellId=(int)std::distance(connI,i);
6691 int sz=endCellId-beginCellId;
6692 int *cells=new int[sz];
6693 for(int j=0;j<sz;j++)
6694 cells[j]=beginCellId+j;
6695 MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
6703 * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
6704 * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
6705 * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
6707 * \return a newly allocated instance, that the caller must manage.
6708 * \throw If \a this contains more than one geometric type.
6709 * \throw If the nodal connectivity of \a this is not fully defined.
6710 * \throw If the internal data is not coherent.
6712 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const throw(INTERP_KERNEL::Exception)
6714 checkConnectivityFullyDefined();
6715 if(_types.size()!=1)
6716 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6717 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6719 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
6720 ret->setCoords(ret->getCoords());
6721 MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6724 int nbCells=getNumberOfCells();
6725 int nbNodesPerCell=retC->getNumberOfNodesPerCell();
6726 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
6727 int *outPtr=connOut->getPointer();
6728 const int *conn=_nodal_connec->begin();
6729 const int *connI=_nodal_connec_index->begin();
6731 for(int i=0;i<nbCells;i++,connI++)
6733 if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
6734 outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
6737 std::ostringstream oss; oss << "MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : 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 << ") !";
6738 throw INTERP_KERNEL::Exception(oss.str().c_str());
6741 retC->setNodalConnectivity(connOut);
6744 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : not implemented yet for non static geometric type !");
6749 * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
6750 * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
6751 * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
6752 * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
6753 * are not used here to avoid the build of big permutation array.
6755 * \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
6756 * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6757 * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
6758 * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
6759 * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
6760 * output array gives for each chunck of same type the corresponding mesh id in \b ms.
6761 * \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
6762 * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6764 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
6765 DataArrayInt *&szOfCellGrpOfSameType,
6766 DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
6768 std::vector<const MEDCouplingUMesh *> ms2;
6769 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
6772 (*it)->checkConnectivityFullyDefined();
6776 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
6777 const DataArrayDouble *refCoo=ms2[0]->getCoords();
6778 int meshDim=ms2[0]->getMeshDimension();
6779 std::vector<const MEDCouplingUMesh *> m1ssm;
6780 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
6782 std::vector<const MEDCouplingUMesh *> m1ssmSingle;
6783 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
6785 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
6786 ret1->alloc(0,1); ret2->alloc(0,1);
6787 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
6789 if(meshDim!=(*it)->getMeshDimension())
6790 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
6791 if(refCoo!=(*it)->getCoords())
6792 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
6793 std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
6794 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
6795 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
6796 for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
6798 MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
6799 m1ssmSingleAuto.push_back(singleCell);
6800 m1ssmSingle.push_back(singleCell);
6801 ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
6804 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
6805 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
6806 std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
6807 for(std::size_t i=0;i<m1ssm.size();i++)
6808 m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
6809 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
6810 szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
6811 idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
6816 * This method returns a newly created DataArrayInt instance.
6817 * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
6819 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
6821 checkFullyDefined();
6822 const int *conn=_nodal_connec->getConstPointer();
6823 const int *connIndex=_nodal_connec_index->getConstPointer();
6824 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
6825 for(const int *w=begin;w!=end;w++)
6826 if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
6827 ret->pushBackSilent(*w);
6832 * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
6833 * are in [0:getNumberOfCells())
6835 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const throw(INTERP_KERNEL::Exception)
6837 checkFullyDefined();
6838 const int *conn=_nodal_connec->getConstPointer();
6839 const int *connI=_nodal_connec_index->getConstPointer();
6840 int nbOfCells=getNumberOfCells();
6841 std::set<INTERP_KERNEL::NormalizedCellType> types=getAllTypes();
6842 int *tmp=new int[nbOfCells];
6843 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6846 for(const int *i=connI;i!=connI+nbOfCells;i++)
6847 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6848 tmp[std::distance(connI,i)]=j++;
6850 DataArrayInt *ret=DataArrayInt::New();
6851 ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
6852 ret->copyStringInfoFrom(*da);
6853 int *retPtr=ret->getPointer();
6854 const int *daPtr=da->getConstPointer();
6855 int nbOfElems=da->getNbOfElems();
6856 for(int k=0;k<nbOfElems;k++)
6857 retPtr[k]=tmp[daPtr[k]];
6863 * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
6864 * This method \b works \b for mesh sorted by type.
6865 * cells whose ids is in 'idsPerGeoType' array.
6866 * This method conserves coords and name of mesh.
6868 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
6870 std::vector<int> code=getDistributionOfTypes();
6871 std::size_t nOfTypesInThis=code.size()/3;
6872 int sz=0,szOfType=0;
6873 for(std::size_t i=0;i<nOfTypesInThis;i++)
6878 szOfType=code[3*i+1];
6880 for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
6881 if(*work<0 || *work>=szOfType)
6883 std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
6884 oss << ". It should be in [0," << szOfType << ") !";
6885 throw INTERP_KERNEL::Exception(oss.str().c_str());
6887 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
6888 int *idsPtr=idsTokeep->getPointer();
6890 for(std::size_t i=0;i<nOfTypesInThis;i++)
6893 for(int j=0;j<code[3*i+1];j++)
6896 idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
6897 offset+=code[3*i+1];
6899 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
6900 ret->copyTinyInfoFrom(this);
6905 * This method returns a vector of size 'this->getNumberOfCells()'.
6906 * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
6908 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const throw(INTERP_KERNEL::Exception)
6910 int ncell=getNumberOfCells();
6911 std::vector<bool> ret(ncell);
6912 const int *cI=getNodalConnectivityIndex()->getConstPointer();
6913 const int *c=getNodalConnectivity()->getConstPointer();
6914 for(int i=0;i<ncell;i++)
6916 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
6917 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6918 ret[i]=cm.isQuadratic();
6924 * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
6926 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
6928 if(other->getType()!=UNSTRUCTURED)
6929 throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
6930 const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
6931 return MergeUMeshes(this,otherC);
6935 * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
6936 * computed by averaging coordinates of cell nodes, so this method is not a right
6937 * choice for degnerated meshes (not well oriented, cells with measure close to zero).
6938 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
6939 * this->getNumberOfCells() tuples per \a this->getSpaceDimension()
6940 * components. The caller is to delete this array using decrRef() as it is
6942 * \throw If the coordinates array is not set.
6943 * \throw If the nodal connectivity of cells is not defined.
6944 * \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
6946 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
6948 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
6949 int spaceDim=getSpaceDimension();
6950 int nbOfCells=getNumberOfCells();
6951 ret->alloc(nbOfCells,spaceDim);
6952 ret->copyStringInfoFrom(*getCoords());
6953 double *ptToFill=ret->getPointer();
6954 const int *nodal=_nodal_connec->getConstPointer();
6955 const int *nodalI=_nodal_connec_index->getConstPointer();
6956 const double *coor=_coords->getConstPointer();
6957 for(int i=0;i<nbOfCells;i++)
6959 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
6960 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
6967 * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
6968 * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the
6970 * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned
6971 * DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
6973 * \sa MEDCouplingUMesh::getBarycenterAndOwner
6974 * \throw If \a this is not fully defined (coordinates and connectivity)
6975 * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
6977 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
6979 checkFullyDefined();
6980 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
6981 int spaceDim=getSpaceDimension();
6982 int nbOfCells=getNumberOfCells();
6983 int nbOfNodes=getNumberOfNodes();
6984 ret->alloc(nbOfCells,spaceDim);
6985 double *ptToFill=ret->getPointer();
6986 const int *nodal=_nodal_connec->getConstPointer();
6987 const int *nodalI=_nodal_connec_index->getConstPointer();
6988 const double *coor=_coords->getConstPointer();
6989 for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
6991 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
6992 std::fill(ptToFill,ptToFill+spaceDim,0.);
6993 if(type!=INTERP_KERNEL::NORM_POLYHED)
6995 for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
6997 if(*conn>=0 && *conn<nbOfNodes)
6998 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7001 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," << nbOfNodes << ") !";
7002 throw INTERP_KERNEL::Exception(oss.str().c_str());
7005 int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7006 if(nbOfNodesInCell>0)
7007 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7010 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7011 throw INTERP_KERNEL::Exception(oss.str().c_str());
7016 std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7018 for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7020 if(*it>=0 && *it<nbOfNodes)
7021 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7024 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," << nbOfNodes << ") !";
7025 throw INTERP_KERNEL::Exception(oss.str().c_str());
7029 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7032 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7033 throw INTERP_KERNEL::Exception(oss.str().c_str());
7041 * Returns a new DataArrayDouble holding barycenters of specified cells. The
7042 * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7043 * are specified via an array of cell ids.
7044 * \warning Validity of the specified cell ids is not checked!
7045 * Valid range is [ 0, \a this->getNumberOfCells() ).
7046 * \param [in] begin - an array of cell ids of interest.
7047 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7048 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7049 * end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7050 * caller is to delete this array using decrRef() as it is no more needed.
7051 * \throw If the coordinates array is not set.
7052 * \throw If the nodal connectivity of cells is not defined.
7054 * \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7055 * \ref py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7057 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7059 DataArrayDouble *ret=DataArrayDouble::New();
7060 int spaceDim=getSpaceDimension();
7061 int nbOfTuple=(int)std::distance(begin,end);
7062 ret->alloc(nbOfTuple,spaceDim);
7063 double *ptToFill=ret->getPointer();
7064 double *tmp=new double[spaceDim];
7065 const int *nodal=_nodal_connec->getConstPointer();
7066 const int *nodalI=_nodal_connec_index->getConstPointer();
7067 const double *coor=_coords->getConstPointer();
7068 for(const int *w=begin;w!=end;w++)
7070 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7071 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7079 * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7082 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da) throw(INTERP_KERNEL::Exception)
7085 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7086 da->checkAllocated();
7087 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName().c_str(),0);
7089 int nbOfTuples=da->getNumberOfTuples();
7090 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7091 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7092 c->alloc(2*nbOfTuples,1);
7093 cI->alloc(nbOfTuples+1,1);
7094 int *cp=c->getPointer();
7095 int *cip=cI->getPointer();
7097 for(int i=0;i<nbOfTuples;i++)
7099 *cp++=INTERP_KERNEL::NORM_POINT1;
7103 ret->setConnectivity(c,cI,true);
7107 * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7108 * Cells and nodes of
7109 * the first mesh precede cells and nodes of the second mesh within the result mesh.
7110 * \param [in] mesh1 - the first mesh.
7111 * \param [in] mesh2 - the second mesh.
7112 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7113 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7114 * is no more needed.
7115 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7116 * \throw If the coordinates array is not set in none of the meshes.
7117 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7118 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7120 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7122 std::vector<const MEDCouplingUMesh *> tmp(2);
7123 tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7124 return MergeUMeshes(tmp);
7128 * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7129 * Cells and nodes of
7130 * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7131 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7132 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7133 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7134 * is no more needed.
7135 * \throw If \a a.size() == 0.
7136 * \throw If \a a[ *i* ] == NULL.
7137 * \throw If the coordinates array is not set in none of the meshes.
7138 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7139 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7141 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7143 std::size_t sz=a.size();
7145 return MergeUMeshesLL(a);
7146 for(std::size_t ii=0;ii<sz;ii++)
7149 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7150 throw INTERP_KERNEL::Exception(oss.str().c_str());
7152 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7153 std::vector< const MEDCouplingUMesh * > aa(sz);
7155 for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7157 const MEDCouplingUMesh *cur=a[i];
7158 const DataArrayDouble *coo=cur->getCoords();
7160 spaceDim=coo->getNumberOfComponents();
7163 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7164 for(std::size_t i=0;i<sz;i++)
7166 bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7169 return MergeUMeshesLL(aa);
7174 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7177 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7178 std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7179 int meshDim=(*it)->getMeshDimension();
7180 int nbOfCells=(*it)->getNumberOfCells();
7181 int meshLgth=(*it++)->getMeshLength();
7182 for(;it!=a.end();it++)
7184 if(meshDim!=(*it)->getMeshDimension())
7185 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7186 nbOfCells+=(*it)->getNumberOfCells();
7187 meshLgth+=(*it)->getMeshLength();
7189 std::vector<const MEDCouplingPointSet *> aps(a.size());
7190 std::copy(a.begin(),a.end(),aps.begin());
7191 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7192 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7193 ret->setCoords(pts);
7194 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7195 c->alloc(meshLgth,1);
7196 int *cPtr=c->getPointer();
7197 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7198 cI->alloc(nbOfCells+1,1);
7199 int *cIPtr=cI->getPointer();
7203 for(it=a.begin();it!=a.end();it++)
7205 int curNbOfCell=(*it)->getNumberOfCells();
7206 const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7207 const int *curC=(*it)->_nodal_connec->getConstPointer();
7208 cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7209 for(int j=0;j<curNbOfCell;j++)
7211 const int *src=curC+curCI[j];
7213 for(;src!=curC+curCI[j+1];src++,cPtr++)
7221 offset+=curCI[curNbOfCell];
7222 offset2+=(*it)->getNumberOfNodes();
7225 ret->setConnectivity(c,cI,true);
7232 * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7233 * dimension and sharing the node coordinates array.
7234 * All cells of the first mesh precede all cells of the second mesh
7235 * within the result mesh.
7236 * \param [in] mesh1 - the first mesh.
7237 * \param [in] mesh2 - the second mesh.
7238 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7239 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7240 * is no more needed.
7241 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7242 * \throw If the meshes do not share the node coordinates array.
7243 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7244 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7246 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7248 std::vector<const MEDCouplingUMesh *> tmp(2);
7249 tmp[0]=mesh1; tmp[1]=mesh2;
7250 return MergeUMeshesOnSameCoords(tmp);
7254 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7255 * dimension and sharing the node coordinates array.
7256 * All cells of the *i*-th mesh precede all cells of the
7257 * (*i*+1)-th mesh within the result mesh.
7258 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7259 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7260 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7261 * is no more needed.
7262 * \throw If \a a.size() == 0.
7263 * \throw If \a a[ *i* ] == NULL.
7264 * \throw If the meshes do not share the node coordinates array.
7265 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7266 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7268 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7271 throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7272 for(std::size_t ii=0;ii<meshes.size();ii++)
7275 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7276 throw INTERP_KERNEL::Exception(oss.str().c_str());
7278 const DataArrayDouble *coords=meshes.front()->getCoords();
7279 int meshDim=meshes.front()->getMeshDimension();
7280 std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7282 int meshIndexLgth=0;
7283 for(;iter!=meshes.end();iter++)
7285 if(coords!=(*iter)->getCoords())
7286 throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7287 if(meshDim!=(*iter)->getMeshDimension())
7288 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7289 meshLgth+=(*iter)->getMeshLength();
7290 meshIndexLgth+=(*iter)->getNumberOfCells();
7292 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7293 nodal->alloc(meshLgth,1);
7294 int *nodalPtr=nodal->getPointer();
7295 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7296 nodalIndex->alloc(meshIndexLgth+1,1);
7297 int *nodalIndexPtr=nodalIndex->getPointer();
7299 for(iter=meshes.begin();iter!=meshes.end();iter++)
7301 const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7302 const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7303 int nbOfCells=(*iter)->getNumberOfCells();
7304 int meshLgth2=(*iter)->getMeshLength();
7305 nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7306 if(iter!=meshes.begin())
7307 nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7309 nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7312 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7313 ret->setName("merge");
7314 ret->setMeshDimension(meshDim);
7315 ret->setConnectivity(nodal,nodalIndex,true);
7316 ret->setCoords(coords);
7321 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7322 * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7323 * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7324 * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7325 * New" mode are returned for each input mesh.
7326 * \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7327 * \param [in] compType - specifies a cell comparison technique. For meaning of its
7328 * valid values [0,1,2], see zipConnectivityTraducer().
7329 * \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7330 * meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7331 * mesh. The caller is to delete each of the arrays using decrRef() as it is
7333 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7334 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7335 * is no more needed.
7336 * \throw If \a meshes.size() == 0.
7337 * \throw If \a meshes[ *i* ] == NULL.
7338 * \throw If the meshes do not share the node coordinates array.
7339 * \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7340 * \throw If the \a meshes are of different dimension (getMeshDimension()).
7341 * \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7342 * \throw If the nodal connectivity any of \a meshes includes an invalid id.
7344 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7346 //All checks are delegated to MergeUMeshesOnSameCoords
7347 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7348 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7349 corr.resize(meshes.size());
7350 std::size_t nbOfMeshes=meshes.size();
7352 const int *o2nPtr=o2n->getConstPointer();
7353 for(std::size_t i=0;i<nbOfMeshes;i++)
7355 DataArrayInt *tmp=DataArrayInt::New();
7356 int curNbOfCells=meshes[i]->getNumberOfCells();
7357 tmp->alloc(curNbOfCells,1);
7358 std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7359 offset+=curNbOfCells;
7360 tmp->setName(meshes[i]->getName());
7367 * Makes all given meshes share the nodal connectivity array. The common connectivity
7368 * array is created by concatenating the connectivity arrays of all given meshes. All
7369 * the given meshes must be of the same space dimension but dimension of cells **can
7370 * differ**. This method is particulary useful in MEDLoader context to build a \ref
7371 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7372 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7373 * \param [in,out] meshes - a vector of meshes to update.
7374 * \throw If any of \a meshes is NULL.
7375 * \throw If the coordinates array is not set in any of \a meshes.
7376 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7377 * \throw If \a meshes are of different space dimension.
7379 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes) throw(INTERP_KERNEL::Exception)
7381 std::size_t sz=meshes.size();
7384 std::vector< const DataArrayDouble * > coords(meshes.size());
7385 std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7386 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7390 (*it)->checkConnectivityFullyDefined();
7391 const DataArrayDouble *coo=(*it)->getCoords();
7396 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7397 oss << " has no coordinate array defined !";
7398 throw INTERP_KERNEL::Exception(oss.str().c_str());
7403 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7404 oss << " is null !";
7405 throw INTERP_KERNEL::Exception(oss.str().c_str());
7408 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7409 std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7410 int offset=(*it)->getNumberOfNodes();
7411 (*it++)->setCoords(res);
7412 for(;it!=meshes.end();it++)
7414 int oldNumberOfNodes=(*it)->getNumberOfNodes();
7415 (*it)->setCoords(res);
7416 (*it)->shiftNodeNumbersInConn(offset);
7417 offset+=oldNumberOfNodes;
7422 * Merges nodes coincident with a given precision within all given meshes that share
7423 * the nodal connectivity array. The given meshes **can be of different** mesh
7424 * dimension. This method is particulary useful in MEDLoader context to build a \ref
7425 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7426 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7427 * \param [in,out] meshes - a vector of meshes to update.
7428 * \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7429 * \throw If any of \a meshes is NULL.
7430 * \throw If the \a meshes do not share the same node coordinates array.
7431 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7433 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps) throw(INTERP_KERNEL::Exception)
7437 std::set<const DataArrayDouble *> s;
7438 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7441 s.insert((*it)->getCoords());
7444 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 !";
7445 throw INTERP_KERNEL::Exception(oss.str().c_str());
7450 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 !";
7451 throw INTERP_KERNEL::Exception(oss.str().c_str());
7453 const DataArrayDouble *coo=*(s.begin());
7457 DataArrayInt *comm,*commI;
7458 coo->findCommonTuples(eps,-1,comm,commI);
7459 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7460 int oldNbOfNodes=coo->getNumberOfTuples();
7462 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7463 if(oldNbOfNodes==newNbOfNodes)
7465 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7466 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7468 (*it)->renumberNodesInConn(o2n->getConstPointer());
7469 (*it)->setCoords(newCoords);
7474 * 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.
7475 * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7476 * \param isQuad specifies the policy of connectivity.
7477 * @ret in/out parameter in which the result will be append
7479 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7481 INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7482 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7483 ret.push_back(cm.getExtrudedType());
7484 int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7487 case INTERP_KERNEL::NORM_POINT1:
7489 ret.push_back(connBg[1]);
7490 ret.push_back(connBg[1]+nbOfNodesPerLev);
7493 case INTERP_KERNEL::NORM_SEG2:
7495 int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7496 ret.insert(ret.end(),conn,conn+4);
7499 case INTERP_KERNEL::NORM_SEG3:
7501 int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
7502 ret.insert(ret.end(),conn,conn+8);
7505 case INTERP_KERNEL::NORM_QUAD4:
7507 int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
7508 ret.insert(ret.end(),conn,conn+8);
7511 case INTERP_KERNEL::NORM_TRI3:
7513 int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
7514 ret.insert(ret.end(),conn,conn+6);
7517 case INTERP_KERNEL::NORM_TRI6:
7519 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,
7520 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
7521 ret.insert(ret.end(),conn,conn+15);
7524 case INTERP_KERNEL::NORM_QUAD8:
7527 connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
7528 connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
7529 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
7531 ret.insert(ret.end(),conn,conn+20);
7534 case INTERP_KERNEL::NORM_POLYGON:
7536 std::back_insert_iterator< std::vector<int> > ii(ret);
7537 std::copy(connBg+1,connEnd,ii);
7539 std::reverse_iterator<const int *> rConnBg(connEnd);
7540 std::reverse_iterator<const int *> rConnEnd(connBg+1);
7541 std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
7542 std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
7543 for(std::size_t i=0;i<nbOfRadFaces;i++)
7546 int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
7547 std::copy(conn,conn+4,ii);
7552 throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
7557 * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
7559 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
7561 double v[3]={0.,0.,0.};
7562 std::size_t sz=std::distance(begin,end);
7565 for(std::size_t i=0;i<sz;i++)
7567 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];
7568 v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
7569 v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
7571 return vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2]>0.;
7575 * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
7577 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
7579 std::vector<std::pair<int,int> > edges;
7580 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7581 const int *bgFace=begin;
7582 for(std::size_t i=0;i<nbOfFaces;i++)
7584 const int *endFace=std::find(bgFace+1,end,-1);
7585 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7586 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7588 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7589 if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
7591 edges.push_back(p1);
7595 return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
7599 * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
7601 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
7603 double vec0[3],vec1[3];
7604 std::size_t sz=std::distance(begin,end);
7606 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
7607 int nbOfNodes=(int)sz/2;
7608 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
7609 const double *pt0=coords+3*begin[0];
7610 const double *pt1=coords+3*begin[nbOfNodes];
7611 vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
7612 return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
7615 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
7617 std::size_t sz=std::distance(begin,end);
7618 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
7619 std::size_t nbOfNodes(sz/2);
7620 std::copy(begin,end,(int *)tmp);
7621 for(std::size_t j=1;j<nbOfNodes;j++)
7623 begin[j]=tmp[nbOfNodes-j];
7624 begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
7628 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
7630 std::size_t sz=std::distance(begin,end);
7632 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
7633 double vec0[3],vec1[3];
7634 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
7635 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];
7636 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;
7639 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
7641 std::size_t sz=std::distance(begin,end);
7643 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
7645 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
7646 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
7647 return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
7651 * 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 )
7652 * 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
7655 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
7656 * \param [in] coords the coordinates with nb of components exactly equal to 3
7657 * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
7658 * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
7659 * \param [out] res the result is put at the end of the vector without any alteration of the data.
7661 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res) throw(INTERP_KERNEL::Exception)
7663 int nbFaces=std::count(begin+1,end,-1)+1;
7664 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
7665 double *vPtr=v->getPointer();
7666 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
7667 double *pPtr=p->getPointer();
7668 const int *stFaceConn=begin+1;
7669 for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
7671 const int *endFaceConn=std::find(stFaceConn,end,-1);
7672 ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
7673 stFaceConn=endFaceConn+1;
7675 pPtr=p->getPointer(); vPtr=v->getPointer();
7676 DataArrayInt *comm1=0,*commI1=0;
7677 v->findCommonTuples(eps,-1,comm1,commI1);
7678 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
7679 const int *comm1Ptr=comm1->getConstPointer();
7680 const int *commI1Ptr=commI1->getConstPointer();
7681 int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
7682 res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
7684 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
7685 mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
7686 mm->finishInsertingCells();
7688 for(int i=0;i<nbOfGrps1;i++)
7690 int vecId=comm1Ptr[commI1Ptr[i]];
7691 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7692 DataArrayInt *comm2=0,*commI2=0;
7693 tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
7694 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
7695 const int *comm2Ptr=comm2->getConstPointer();
7696 const int *commI2Ptr=commI2->getConstPointer();
7697 int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
7698 for(int j=0;j<nbOfGrps2;j++)
7700 if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
7702 res->insertAtTheEnd(begin,end);
7703 res->pushBackSilent(-1);
7707 int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
7708 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
7709 ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7710 DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
7711 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
7712 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
7713 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
7714 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
7715 const int *idsNodePtr=idsNode->getConstPointer();
7716 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];
7717 double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
7718 double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
7719 if(std::abs(norm)>eps)
7721 double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
7722 mm3->rotate(center,vec,angle);
7724 mm3->changeSpaceDimension(2);
7725 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
7726 const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
7727 const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
7728 int nbOfCells=mm4->getNumberOfCells();
7729 for(int k=0;k<nbOfCells;k++)
7732 for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
7733 res->pushBackSilent(idsNodePtr[*work]);
7734 res->pushBackSilent(-1);
7739 res->popBackSilent();
7743 * 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
7744 * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
7746 * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
7747 * \param [in] coords coordinates expected to have 3 components.
7748 * \param [in] begin start of the nodal connectivity of the face.
7749 * \param [in] end end of the nodal connectivity (excluded) of the face.
7750 * \param [out] v the normalized vector of size 3
7751 * \param [out] p the pos of plane
7753 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p) throw(INTERP_KERNEL::Exception)
7755 std::size_t nbPoints=std::distance(begin,end);
7757 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
7758 double vec[3]={0.,0.,0.};
7760 bool refFound=false;
7761 for(;j<nbPoints-1 && !refFound;j++)
7763 vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
7764 vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
7765 vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
7766 double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
7770 vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
7773 for(std::size_t i=j;i<nbPoints-1;i++)
7776 curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
7777 curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
7778 curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
7779 double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
7782 curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
7783 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];
7784 norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
7787 v[0]/=norm; v[1]/=norm; v[2]/=norm;
7788 *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
7792 throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
7796 * This method tries to obtain a well oriented polyhedron.
7797 * If the algorithm fails, an exception will be thrown.
7799 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords) throw(INTERP_KERNEL::Exception)
7801 std::list< std::pair<int,int> > edgesOK,edgesFinished;
7802 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7803 std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
7805 int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
7806 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7807 for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
7809 while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
7812 std::size_t smthChanged=0;
7813 for(std::size_t i=0;i<nbOfFaces;i++)
7815 endFace=std::find(bgFace+1,end,-1);
7816 nbOfEdgesInFace=std::distance(bgFace,endFace);
7820 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7822 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7823 std::pair<int,int> p2(p1.second,p1.first);
7824 bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
7825 bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
7826 if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
7831 std::reverse(bgFace+1,endFace);
7832 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7834 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7835 std::pair<int,int> p2(p1.second,p1.first);
7836 if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
7837 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7838 if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
7839 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7840 std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
7841 if(it!=edgesOK.end())
7844 edgesFinished.push_back(p1);
7847 edgesOK.push_back(p1);
7854 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
7856 if(!edgesOK.empty())
7857 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
7858 if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
7859 {//not lucky ! The first face was not correctly oriented : reorient all faces...
7861 for(std::size_t i=0;i<nbOfFaces;i++)
7863 endFace=std::find(bgFace+1,end,-1);
7864 std::reverse(bgFace+1,endFace);
7871 * This method makes the assumption spacedimension == meshdimension == 2.
7872 * This method works only for linear cells.
7874 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
7876 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const throw(INTERP_KERNEL::Exception)
7878 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
7879 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
7880 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
7881 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=m->zipCoordsTraducer();
7882 int nbOfNodesExpected=m->getNumberOfNodes();
7883 if(m->getNumberOfCells()!=nbOfNodesExpected)
7884 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part or a quadratic 2D mesh !");
7885 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(m->getNumberOfNodes());
7886 const int *n2oPtr=n2o->getConstPointer();
7887 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
7888 m->getReverseNodalConnectivity(revNodal,revNodalI);
7889 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
7890 const int *nodalPtr=m->getNodalConnectivity()->getConstPointer();
7891 const int *nodalIPtr=m->getNodalConnectivityIndex()->getConstPointer();
7892 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodesExpected+1,1);
7893 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYGON;
7894 if(nbOfNodesExpected<1)
7897 int prevNode=nodalPtr[nodalIPtr[0]+1];
7898 *work++=n2oPtr[prevNode];
7899 for(int i=1;i<nbOfNodesExpected;i++)
7901 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
7903 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
7904 conn.erase(prevNode);
7907 int curNode=*(conn.begin());
7908 *work++=n2oPtr[curNode];
7909 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
7910 shar.erase(prevCell);
7913 prevCell=*(shar.begin());
7917 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 2 !");
7920 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 1 !");
7923 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected cell !");
7929 * This method makes the assumption spacedimension == meshdimension == 3.
7930 * This method works only for linear cells.
7932 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
7934 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const throw(INTERP_KERNEL::Exception)
7936 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
7937 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
7938 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
7939 const int *conn=m->getNodalConnectivity()->getConstPointer();
7940 const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
7941 int nbOfCells=m->getNumberOfCells();
7942 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
7943 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED;
7946 work=std::copy(conn+connI[0]+1,conn+connI[1],work);
7947 for(int i=1;i<nbOfCells;i++)
7950 work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
7956 * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
7957 * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
7959 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt) throw(INTERP_KERNEL::Exception)
7963 for(int i=0;i<nbOfNodesInCell;i++)
7964 w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
7965 else if(spaceDim==2)
7967 for(int i=0;i<nbOfNodesInCell;i++)
7969 w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
7974 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
7977 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData) const throw(INTERP_KERNEL::Exception)
7979 int nbOfCells=getNumberOfCells();
7981 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
7982 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,-1,4};
7983 ofs << " <" << getVTKDataSetType() << ">\n";
7984 ofs << " <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
7985 ofs << " <PointData>\n" << pointData << std::endl;
7986 ofs << " </PointData>\n";
7987 ofs << " <CellData>\n" << cellData << std::endl;
7988 ofs << " </CellData>\n";
7989 ofs << " <Points>\n";
7990 if(getSpaceDimension()==3)
7991 _coords->writeVTK(ofs,8,"Points");
7994 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
7995 coo->writeVTK(ofs,8,"Points");
7997 ofs << " </Points>\n";
7998 ofs << " <Cells>\n";
7999 const int *cPtr=_nodal_connec->getConstPointer();
8000 const int *cIPtr=_nodal_connec_index->getConstPointer();
8001 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8002 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8003 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8004 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8005 int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8006 int szFaceOffsets=0,szConn=0;
8007 for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8010 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8013 *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8014 w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8018 int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8019 *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8020 std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8021 *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8022 w4=std::copy(c.begin(),c.end(),w4);
8025 types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
8026 types->writeVTK(ofs,8,"UInt8","types");
8027 offsets->writeVTK(ofs,8,"Int32","offsets");
8028 if(szFaceOffsets!=0)
8029 {//presence of Polyhedra
8030 connectivity->reAlloc(szConn);
8031 faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets");
8032 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8033 w1=faces->getPointer();
8034 for(int i=0;i<nbOfCells;i++)
8035 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8037 int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8039 const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8040 for(int j=0;j<nbFaces;j++)
8042 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8043 *w1++=(int)std::distance(w6,w5);
8044 w1=std::copy(w6,w5,w1);
8048 faces->writeVTK(ofs,8,"Int32","faces");
8050 connectivity->writeVTK(ofs,8,"Int32","connectivity");
8051 ofs << " </Cells>\n";
8052 ofs << " </Piece>\n";
8053 ofs << " </" << getVTKDataSetType() << ">\n";
8056 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
8058 stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8060 { stream << " Not set !"; return ; }
8061 stream << " Mesh dimension : " << _mesh_dim << ".";
8065 { stream << " No coordinates set !"; return ; }
8066 if(!_coords->isAllocated())
8067 { stream << " Coordinates set but not allocated !"; return ; }
8068 stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8069 stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8070 if(!_nodal_connec_index)
8071 { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8072 if(!_nodal_connec_index->isAllocated())
8073 { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8074 int lgth=_nodal_connec_index->getNumberOfTuples();
8075 int cpt=_nodal_connec_index->getNumberOfComponents();
8076 if(cpt!=1 || lgth<1)
8078 stream << std::endl << "Number of cells : " << lgth-1 << ".";
8081 std::string MEDCouplingUMesh::getVTKDataSetType() const throw(INTERP_KERNEL::Exception)
8083 return std::string("UnstructuredGrid");
8087 * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8088 * returns a result mesh constituted by polygons. The meshes should be in 2D space. In
8089 * addition, returns two arrays mapping cells of the result mesh to cells of the input
8091 * \param [in] m1 - the first input mesh which is a partitioned object.
8092 * \param [in] m2 - the second input mesh which is a partition tool.
8093 * \param [in] eps - precision used to detect coincident mesh entities.
8094 * \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8095 * cell an id of the cell of \a m1 it comes from. The caller is to delete
8096 * this array using decrRef() as it is no more needed.
8097 * \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8098 * cell an id of the cell of \a m2 it comes from. -1 value means that a
8099 * result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8100 * any cell of \a m2. The caller is to delete this array using decrRef() as
8101 * it is no more needed.
8102 * \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8103 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8104 * is no more needed.
8105 * \throw If the coordinates array is not set in any of the meshes.
8106 * \throw If the nodal connectivity of cells is not defined in any of the meshes.
8107 * \throw If any of the meshes is not a 2D mesh in 2D space.
8109 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2) throw(INTERP_KERNEL::Exception)
8111 m1->checkFullyDefined();
8112 m2->checkFullyDefined();
8113 if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8114 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!");
8115 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8116 MEDCouplingUMesh *m1Desc=0,*m2Desc=0;
8117 DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8118 std::vector<double> addCoo,addCoordsQuadratic;
8119 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8120 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8121 IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8122 m2Desc,desc2,descIndx2,revDesc2,revDescIndx2,addCoo);
8123 revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8124 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8125 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8126 std::vector< std::vector<int> > intersectEdge2;
8127 BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8128 subDiv2.clear(); dd5=0; dd6=0;
8129 std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8130 std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8131 BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8132 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8134 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
8135 addCooDa->alloc((int)(addCoo.size())/2,2);
8136 std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8137 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
8138 addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8139 std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8140 std::vector<const DataArrayDouble *> coordss(4);
8141 coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8142 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
8143 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
8144 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8145 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8146 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8147 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8148 ret->setConnectivity(conn,connI,true);
8149 ret->setCoords(coo);
8150 cellNb1=c1.retn(); cellNb2=c2.retn();
8154 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8155 const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8156 const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8157 const std::vector<double>& addCoords,
8158 std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8160 static const int SPACEDIM=2;
8161 std::vector<double> bbox1,bbox2;
8162 const double *coo1=m1->getCoords()->getConstPointer();
8163 const int *conn1=m1->getNodalConnectivity()->getConstPointer();
8164 const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
8165 int offset1=m1->getNumberOfNodes();
8166 const double *coo2=m2->getCoords()->getConstPointer();
8167 const int *conn2=m2->getNodalConnectivity()->getConstPointer();
8168 const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
8169 int offset2=offset1+m2->getNumberOfNodes();
8170 int offset3=offset2+((int)addCoords.size())/2;
8171 m1->getBoundingBoxForBBTree(bbox1);
8172 m2->getBoundingBoxForBBTree(bbox2);
8173 BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2->getNumberOfCells(),eps);
8174 int ncell1=m1->getNumberOfCells();
8176 for(int i=0;i<ncell1;i++)
8178 std::vector<int> candidates2;
8179 myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
8180 std::map<INTERP_KERNEL::Node *,int> mapp;
8181 std::map<int,INTERP_KERNEL::Node *> mappRev;
8182 INTERP_KERNEL::QuadraticPolygon pol1;
8183 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8184 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8185 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8186 pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8187 desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8189 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
8190 std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8191 INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8192 for(it1.first();!it1.finished();it1.next())
8193 edges1.insert(it1.current()->getPtr());
8195 std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare;
8196 std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8198 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8200 INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8201 const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8202 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8203 pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8204 pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2,edgesIn2ForShare);
8207 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8209 pol1.initLocationsWithOther(pol2s[ii]);
8210 pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8211 //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8212 pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8218 INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8220 catch(INTERP_KERNEL::Exception& e)
8222 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();
8223 throw INTERP_KERNEL::Exception(oss.str().c_str());
8226 for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8227 (*it).second->decrRef();
8232 * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
8235 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
8236 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
8237 MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
8238 MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2,
8239 std::vector<double>& addCoo) throw(INTERP_KERNEL::Exception)
8241 static const int SPACEDIM=2;
8242 desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
8243 desc2=DataArrayInt::New();
8244 descIndx2=DataArrayInt::New();
8245 revDesc2=DataArrayInt::New();
8246 revDescIndx2=DataArrayInt::New();
8247 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
8248 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
8249 m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
8250 m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
8251 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
8252 const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
8253 const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
8254 std::vector<double> bbox1,bbox2;
8255 m1Desc->getBoundingBoxForBBTree(bbox1);
8256 m2Desc->getBoundingBoxForBBTree(bbox2);
8257 int ncell1=m1Desc->getNumberOfCells();
8258 int ncell2=m2Desc->getNumberOfCells();
8259 intersectEdge1.resize(ncell1);
8260 colinear2.resize(ncell2);
8261 subDiv2.resize(ncell2);
8262 BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2Desc->getNumberOfCells(),-eps);
8263 std::vector<int> candidates1(1);
8264 int offset1=m1->getNumberOfNodes();
8265 int offset2=offset1+m2->getNumberOfNodes();
8266 for(int i=0;i<ncell1;i++)
8268 std::vector<int> candidates2;
8269 myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
8270 if(!candidates2.empty())
8272 std::map<INTERP_KERNEL::Node *,int> map1,map2;
8273 INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
8275 INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
8276 pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
8281 intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
8283 m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
8284 m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
8288 * This method performs the 2nd step of Partition of 2D mesh.
8289 * This method has 4 inputs :
8290 * - a mesh 'm1' with meshDim==1 and a SpaceDim==2
8291 * - a mesh 'm2' with meshDim==1 and a SpaceDim==2
8292 * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids in randomly sorted.
8293 * The aim of this method is to sort the splitting nodes, if any, and to put in 'intersectEdge' output paramter based on edges of mesh 'm2'
8294 * \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. Only present for its coords in case of 'subDiv' shares some nodes of 'm1'
8295 * \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.
8296 * \param addCoo input parameter with additionnal nodes linked to intersection of the 2 meshes.
8298 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, const std::vector<double>& addCoo, const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge) throw(INTERP_KERNEL::Exception)
8300 int offset1=m1->getNumberOfNodes();
8301 int ncell=m2->getNumberOfCells();
8302 const int *c=m2->getNodalConnectivity()->getConstPointer();
8303 const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
8304 const double *coo=m2->getCoords()->getConstPointer();
8305 const double *cooBis=m1->getCoords()->getConstPointer();
8306 int offset2=offset1+m2->getNumberOfNodes();
8307 intersectEdge.resize(ncell);
8308 for(int i=0;i<ncell;i++,cI++)
8310 const std::vector<int>& divs=subDiv[i];
8311 int nnode=cI[1]-cI[0]-1;
8312 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
8313 std::map<INTERP_KERNEL::Node *, int> mapp22;
8314 for(int j=0;j<nnode;j++)
8316 INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
8317 int nnid=c[(*cI)+j+1];
8318 mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
8319 mapp22[nn]=nnid+offset1;
8321 INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
8322 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
8323 ((*it).second.first)->decrRef();
8324 std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
8325 std::map<INTERP_KERNEL::Node *,int> mapp3;
8326 for(std::size_t j=0;j<divs.size();j++)
8329 INTERP_KERNEL::Node *tmp=0;
8331 tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
8333 tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
8335 tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
8339 e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
8340 for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
8347 * 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).
8348 * 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
8349 * with a plane. The result will be put in 'cut3DSuf' out parameter.
8350 * \param [in] cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
8351 * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
8352 * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
8353 * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
8354 * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
8355 * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
8356 * \param [in] desc is the descending connectivity 3DSurf->3DCurve
8357 * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
8358 * \param [out] cut3DSuf input/output param.
8360 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
8361 const int *nodal3DCurve, const int *nodalIndx3DCurve,
8362 const int *desc, const int *descIndx,
8363 std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
8365 std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
8366 int nbOf3DSurfCell=(int)cut3DSurf.size();
8367 for(int i=0;i<nbOf3DSurfCell;i++)
8369 std::vector<int> res;
8370 int offset=descIndx[i];
8371 int nbOfSeg=descIndx[i+1]-offset;
8372 for(int j=0;j<nbOfSeg;j++)
8374 int edgeId=desc[offset+j];
8375 int status=cut3DCurve[edgeId];
8379 res.push_back(status);
8382 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
8383 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
8391 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8397 std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
8398 std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
8401 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8405 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
8410 {// case when plane is on a multi colinear edge of a polyhedron
8411 if((int)res.size()==2*nbOfSeg)
8413 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
8416 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
8423 * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
8424 * 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).
8425 * 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
8426 * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
8427 * \param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
8428 * \param desc is the descending connectivity 3D->3DSurf
8429 * \param descIndx is the descending connectivity index 3D->3DSurf
8431 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
8432 const int *desc, const int *descIndx,
8433 DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
8435 checkFullyDefined();
8436 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8437 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
8438 const int *nodal3D=_nodal_connec->getConstPointer();
8439 const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
8440 int nbOfCells=getNumberOfCells();
8441 for(int i=0;i<nbOfCells;i++)
8443 std::map<int, std::set<int> > m;
8444 int offset=descIndx[i];
8445 int nbOfFaces=descIndx[i+1]-offset;
8448 for(int j=0;j<nbOfFaces;j++)
8450 const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
8451 if(p.first!=-1 && p.second!=-1)
8455 start=p.first; end=p.second;
8456 m[p.first].insert(p.second);
8457 m[p.second].insert(p.first);
8461 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
8462 int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
8463 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8464 INTERP_KERNEL::NormalizedCellType cmsId;
8465 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
8466 start=tmp[0]; end=tmp[nbOfNodesSon-1];
8467 for(unsigned k=0;k<nbOfNodesSon;k++)
8469 m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
8470 m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
8477 std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
8481 std::map<int, std::set<int> >::const_iterator it=m.find(start);
8482 const std::set<int>& s=(*it).second;
8483 std::set<int> s2; s2.insert(prev);
8485 std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
8488 int val=*s3.begin();
8489 conn.push_back(start);
8496 conn.push_back(end);
8499 nodalRes->insertAtTheEnd(conn.begin(),conn.end());
8500 nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
8501 cellIds->pushBackSilent(i);
8507 * 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
8508 * 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
8509 * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
8510 * 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
8511 * 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.
8513 * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
8515 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut) throw(INTERP_KERNEL::Exception)
8517 std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
8520 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
8521 if(cm.getDimension()==2)
8523 const int *node=nodalConnBg+1;
8524 int startNode=*node++;
8525 double refX=coords[2*startNode];
8526 for(;node!=nodalConnEnd;node++)
8528 if(coords[2*(*node)]<refX)
8531 refX=coords[2*startNode];
8534 std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
8538 double angle0=-M_PI/2;
8543 double angleNext=0.;
8544 while(nextNode!=startNode)
8548 for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
8550 if(*node!=tmpOut.back() && *node!=prevNode)
8552 tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
8553 double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
8558 res=angle0-angleM+2.*M_PI;
8567 if(nextNode!=startNode)
8569 angle0=angleNext-M_PI;
8572 prevNode=tmpOut.back();
8573 tmpOut.push_back(nextNode);
8576 std::vector<int> tmp3(2*(sz-1));
8577 std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
8578 std::copy(nodalConnBg+1,nodalConnEnd,it);
8579 if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
8581 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8584 if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
8586 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8591 nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
8592 nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
8597 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8600 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8604 * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
8605 * 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.
8607 * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
8608 * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
8609 * \param [in,out] arr array in which the remove operation will be done.
8610 * \param [in,out] arrIndx array in the remove operation will modify
8611 * \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])
8612 * \return true if \b arr and \b arrIndx have been modified, false if not.
8614 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval) throw(INTERP_KERNEL::Exception)
8616 if(!arrIndx || !arr)
8617 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
8618 if(offsetForRemoval<0)
8619 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
8620 std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
8621 int nbOfGrps=arrIndx->getNumberOfTuples()-1;
8622 int *arrIPtr=arrIndx->getPointer();
8625 const int *arrPtr=arr->getConstPointer();
8626 std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
8627 for(int i=0;i<nbOfGrps;i++,arrIPtr++)
8629 if(*arrIPtr-previousArrI>offsetForRemoval)
8631 for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
8633 if(s.find(*work)==s.end())
8634 arrOut.push_back(*work);
8637 previousArrI=*arrIPtr;
8638 *arrIPtr=(int)arrOut.size();
8640 if(arr->getNumberOfTuples()==(int)arrOut.size())
8642 arr->alloc((int)arrOut.size(),1);
8643 std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
8648 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8649 * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
8650 * The selection of extraction is done standardly in new2old format.
8651 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8653 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8654 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8655 * \param [in] arrIn arr origin array from which the extraction will be done.
8656 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8657 * \param [out] arrOut the resulting array
8658 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8660 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8661 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8663 if(!arrIn || !arrIndxIn)
8664 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
8665 std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
8666 const int *arrInPtr=arrIn->getConstPointer();
8667 const int *arrIndxPtr=arrIndxIn->getConstPointer();
8668 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8669 int maxSizeOfArr=arrIn->getNumberOfTuples();
8670 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8671 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8672 arrIo->alloc((int)(sz+1),1);
8673 const int *idsIt=idsOfSelectBg;
8674 int *work=arrIo->getPointer();
8677 for(std::size_t i=0;i<sz;i++,work++,idsIt++)
8679 if(*idsIt>=0 && *idsIt<nbOfGrps)
8680 lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
8683 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8684 throw INTERP_KERNEL::Exception(oss.str().c_str());
8690 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
8691 oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
8692 throw INTERP_KERNEL::Exception(oss.str().c_str());
8695 arro->alloc(lgth,1);
8696 work=arro->getPointer();
8697 idsIt=idsOfSelectBg;
8698 for(std::size_t i=0;i<sz;i++,idsIt++)
8700 if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
8701 work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
8704 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
8705 oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8706 throw INTERP_KERNEL::Exception(oss.str().c_str());
8710 arrIndexOut=arrIo.retn();
8714 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8715 * 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
8716 * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8717 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8719 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8720 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8721 * \param [in] arrIn arr origin array from which the extraction will be done.
8722 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8723 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
8724 * \param [in] srcArrIndex index array of \b srcArr
8725 * \param [out] arrOut the resulting array
8726 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8728 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
8730 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8731 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8732 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8734 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8735 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
8736 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8737 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8738 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8739 std::vector<bool> v(nbOfTuples,true);
8741 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8742 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8743 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8745 if(*it>=0 && *it<nbOfTuples)
8748 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
8752 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8753 throw INTERP_KERNEL::Exception(oss.str().c_str());
8756 srcArrIndexPtr=srcArrIndex->getConstPointer();
8757 arrIo->alloc(nbOfTuples+1,1);
8758 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8759 const int *arrInPtr=arrIn->getConstPointer();
8760 const int *srcArrPtr=srcArr->getConstPointer();
8761 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8762 int *arroPtr=arro->getPointer();
8763 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8767 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
8768 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
8772 std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
8773 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
8774 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
8778 arrIndexOut=arrIo.retn();
8782 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8783 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
8785 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8786 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8787 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
8788 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8789 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
8790 * \param [in] srcArrIndex index array of \b srcArr
8792 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
8794 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
8795 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
8797 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8798 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
8799 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8800 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8801 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8802 int *arrInOutPtr=arrInOut->getPointer();
8803 const int *srcArrPtr=srcArr->getConstPointer();
8804 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8806 if(*it>=0 && *it<nbOfTuples)
8808 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
8809 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
8812 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] !";
8813 throw INTERP_KERNEL::Exception(oss.str().c_str());
8818 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8819 throw INTERP_KERNEL::Exception(oss.str().c_str());
8825 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8826 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8827 * 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]].
8828 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
8829 * A negative value in \b arrIn means that it is ignored.
8830 * 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.
8832 * \param [in] arrIn arr origin array from which the extraction will be done.
8833 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8834 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
8835 * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
8837 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn) throw(INTERP_KERNEL::Exception)
8839 int seed=0,nbOfDepthPeelingPerformed=0;
8840 return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
8844 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8845 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8846 * 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]].
8847 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
8848 * A negative value in \b arrIn means that it is ignored.
8849 * 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.
8850 * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
8851 * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
8852 * \param [in] arrIn arr origin array from which the extraction will be done.
8853 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8854 * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
8855 * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
8856 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
8857 * \sa MEDCouplingUMesh::partitionBySpreadZone
8859 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception)
8861 nbOfDepthPeelingPerformed=0;
8863 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
8864 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8867 DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
8871 std::vector<bool> fetched(nbOfTuples,false);
8872 return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
8875 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception)
8877 nbOfDepthPeelingPerformed=0;
8878 if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
8879 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
8880 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8881 std::vector<bool> fetched2(nbOfTuples,false);
8883 for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
8885 if(*seedElt>=0 && *seedElt<nbOfTuples)
8886 { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
8888 { 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()); }
8890 const int *arrInPtr=arrIn->getConstPointer();
8891 const int *arrIndxPtr=arrIndxIn->getConstPointer();
8892 int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
8893 std::vector<int> idsToFetch1(seedBg,seedEnd);
8894 std::vector<int> idsToFetch2;
8895 std::vector<int> *idsToFetch=&idsToFetch1;
8896 std::vector<int> *idsToFetchOther=&idsToFetch2;
8897 while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
8899 for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
8900 for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
8902 { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
8903 std::swap(idsToFetch,idsToFetchOther);
8904 idsToFetchOther->clear();
8905 nbOfDepthPeelingPerformed++;
8907 int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
8909 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
8910 int *retPtr=ret->getPointer();
8911 for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
8918 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8919 * 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
8920 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8921 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8923 * \param [in] start begin of set of ids of the input extraction (included)
8924 * \param [in] end end of set of ids of the input extraction (excluded)
8925 * \param [in] step step of the set of ids in range mode.
8926 * \param [in] arrIn arr origin array from which the extraction will be done.
8927 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8928 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8929 * \param [in] srcArrIndex index array of \b srcArr
8930 * \param [out] arrOut the resulting array
8931 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8933 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
8935 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8936 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8937 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8939 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8940 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
8941 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8942 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8943 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8945 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8946 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8947 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
8949 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
8951 if(it>=0 && it<nbOfTuples)
8952 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
8955 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
8956 throw INTERP_KERNEL::Exception(oss.str().c_str());
8959 srcArrIndexPtr=srcArrIndex->getConstPointer();
8960 arrIo->alloc(nbOfTuples+1,1);
8961 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8962 const int *arrInPtr=arrIn->getConstPointer();
8963 const int *srcArrPtr=srcArr->getConstPointer();
8964 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8965 int *arroPtr=arro->getPointer();
8966 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8968 int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
8971 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
8972 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
8976 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
8977 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
8981 arrIndexOut=arrIo.retn();
8985 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8986 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
8988 * \param [in] start begin of set of ids of the input extraction (included)
8989 * \param [in] end end of set of ids of the input extraction (excluded)
8990 * \param [in] step step of the set of ids in range mode.
8991 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
8992 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8993 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8994 * \param [in] srcArrIndex index array of \b srcArr
8996 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
8998 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
8999 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9001 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9002 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
9003 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9004 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9005 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9006 int *arrInOutPtr=arrInOut->getPointer();
9007 const int *srcArrPtr=srcArr->getConstPointer();
9008 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
9010 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9012 if(it>=0 && it<nbOfTuples)
9014 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
9015 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
9018 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9019 throw INTERP_KERNEL::Exception(oss.str().c_str());
9024 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9025 throw INTERP_KERNEL::Exception(oss.str().c_str());
9031 * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
9032 * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
9033 * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
9034 * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
9035 * The sum of measure field of returned mesh is equal to the sum of measure field of this.
9037 * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
9039 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const throw(INTERP_KERNEL::Exception)
9041 checkFullyDefined();
9042 int mdim=getMeshDimension();
9043 int spaceDim=getSpaceDimension();
9045 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
9046 std::vector<DataArrayInt *> partition=partitionBySpreadZone();
9047 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
9048 std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
9049 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
9050 ret->setCoords(getCoords());
9051 ret->allocateCells((int)partition.size());
9053 for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
9055 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
9056 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
9060 cell=tmp->buildUnionOf2DMesh();
9063 cell=tmp->buildUnionOf3DMesh();
9066 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
9069 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
9072 ret->finishInsertingCells();
9077 * This method partitions \b this into contiguous zone.
9078 * This method only needs a well defined connectivity. Coordinates are not considered here.
9079 * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
9081 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const throw(INTERP_KERNEL::Exception)
9084 int nbOfCellsCur=getNumberOfCells();
9085 std::vector<DataArrayInt *> ret;
9088 DataArrayInt *neigh=0,*neighI=0;
9089 computeNeighborsOfCells(neigh,neighI);
9090 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9091 std::vector<bool> fetchedCells(nbOfCellsCur,false);
9092 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9094 while(seed<nbOfCellsCur)
9096 int nbOfPeelPerformed=0;
9097 ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
9098 seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
9100 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
9101 ret.push_back((*it).retn());
9105 int nbOfCellsCur=getNumberOfCells();
9106 DataArrayInt *neigh=0,*neighI=0;
9107 computeNeighborsOfCells(neigh,neighI);
9108 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9109 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=DataArrayInt::New(); ids->alloc(nbOfCellsCur,1); ids->iota();
9110 std::vector<DataArrayInt *> ret;
9111 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9112 while(nbOfCellsCur>0)
9114 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=MEDCouplingUMesh::ComputeSpreadZoneGradually(neighAuto,neighIAuto);
9115 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=tmp->buildComplement(nbOfCellsCur);
9116 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=ids->selectByTupleId(tmp->begin(),tmp->end());
9117 ret2.push_back(tmp2); ret.push_back(tmp2);
9118 nbOfCellsCur=tmp3->getNumberOfTuples();
9121 ids=ids->selectByTupleId(tmp3->begin(),tmp3->end());
9122 MEDCouplingUMesh::ExtractFromIndexedArrays(tmp3->begin(),tmp3->end(),neighAuto,neighIAuto,neigh,neighI);
9125 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=tmp3->invertArrayN2O2O2N(nbOfCellsCur+tmp->getNumberOfTuples());
9126 neighAuto->transformWithIndArr(renum->begin(),renum->end());
9129 for(std::vector<DataArrayInt *>::const_iterator it=ret.begin();it!=ret.end();it++)
9136 * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
9137 * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
9139 * \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.
9140 * \return a newly allocated DataArrayInt to be managed by the caller.
9141 * \throw In case of \a code has not the right format (typically of size 3*n)
9143 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code) throw(INTERP_KERNEL::Exception)
9145 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
9146 std::size_t nb=code.size()/3;
9147 if(code.size()%3!=0)
9148 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
9149 ret->alloc((int)nb,2);
9150 int *retPtr=ret->getPointer();
9151 for(std::size_t i=0;i<nb;i++,retPtr+=2)
9153 retPtr[0]=code[3*i+2];
9154 retPtr[1]=code[3*i+2]+code[3*i+1];
9159 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
9160 _own_cell(true),_cell_id(-1),_nb_cell(0)
9165 _nb_cell=mesh->getNumberOfCells();
9169 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
9177 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
9178 _own_cell(false),_cell_id(bg-1),
9185 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
9188 if(_cell_id<_nb_cell)
9197 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
9203 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
9205 return new MEDCouplingUMeshCellByTypeIterator(_mesh);
9208 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
9214 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
9222 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
9228 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
9233 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
9238 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
9240 return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
9243 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
9248 _nb_cell=mesh->getNumberOfCells();
9252 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
9259 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
9261 const int *c=_mesh->getNodalConnectivity()->getConstPointer();
9262 const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
9263 if(_cell_id<_nb_cell)
9265 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
9266 int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
9267 int startId=_cell_id;
9268 _cell_id+=nbOfElems;
9269 return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
9275 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
9279 _conn=mesh->getNodalConnectivity()->getPointer();
9280 _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
9284 void MEDCouplingUMeshCell::next()
9286 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9291 _conn_lgth=_conn_indx[1]-_conn_indx[0];
9294 std::string MEDCouplingUMeshCell::repr() const
9296 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9298 std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
9300 std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
9304 return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
9307 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
9309 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9310 return (INTERP_KERNEL::NormalizedCellType)_conn[0];
9312 return INTERP_KERNEL::NORM_ERROR;
9315 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
9318 if(_conn_lgth!=NOTICABLE_FIRST_VAL)