1 // Copyright (C) 2007-2014 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 // Author : Anthony Geay (CEA/DEN)
21 #include "MEDCouplingUMesh.hxx"
22 #include "MEDCoupling1GTUMesh.hxx"
23 #include "MEDCouplingMemArray.txx"
24 #include "MEDCouplingFieldDouble.hxx"
25 #include "CellModel.hxx"
26 #include "VolSurfUser.txx"
27 #include "InterpolationUtils.hxx"
28 #include "PointLocatorAlgos.txx"
30 #include "BBTreeDst.txx"
31 #include "SplitterTetra.hxx"
32 #include "DirectedBoundingBox.hxx"
33 #include "InterpKernelMatrixTools.hxx"
34 #include "InterpKernelMeshQuality.hxx"
35 #include "InterpKernelCellSimplify.hxx"
36 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
37 #include "InterpKernelAutoPtr.hxx"
38 #include "InterpKernelGeo2DNode.hxx"
39 #include "InterpKernelGeo2DEdgeLin.hxx"
40 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
41 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
50 using namespace ParaMEDMEM;
52 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
54 const INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::MEDMEM_ORDER[N_MEDMEM_ORDER] = { INTERP_KERNEL::NORM_POINT1, INTERP_KERNEL::NORM_SEG2, INTERP_KERNEL::NORM_SEG3, INTERP_KERNEL::NORM_SEG4, INTERP_KERNEL::NORM_POLYL, INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_TRI7, INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_QUAD9, INTERP_KERNEL::NORM_POLYGON, INTERP_KERNEL::NORM_QPOLYG, INTERP_KERNEL::NORM_TETRA4, INTERP_KERNEL::NORM_PYRA5, INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXA8, INTERP_KERNEL::NORM_HEXGP12, INTERP_KERNEL::NORM_TETRA10, INTERP_KERNEL::NORM_PYRA13, INTERP_KERNEL::NORM_PENTA15, INTERP_KERNEL::NORM_HEXA20, INTERP_KERNEL::NORM_HEXA27, INTERP_KERNEL::NORM_POLYHED };
56 MEDCouplingUMesh *MEDCouplingUMesh::New()
58 return new MEDCouplingUMesh;
61 MEDCouplingUMesh *MEDCouplingUMesh::New(const std::string& meshName, int meshDim)
63 MEDCouplingUMesh *ret=new MEDCouplingUMesh;
64 ret->setName(meshName);
65 ret->setMeshDimension(meshDim);
70 * Returns a new MEDCouplingMesh which is a full copy of \a this one. No data is shared
71 * between \a this and the new mesh.
72 * \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
73 * delete this mesh using decrRef() as it is no more needed.
75 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
81 * Returns a new MEDCouplingMesh which is a copy of \a this one.
82 * \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
83 * this mesh are shared by the new mesh.
84 * \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
85 * delete this mesh using decrRef() as it is no more needed.
87 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
89 return new MEDCouplingUMesh(*this,recDeepCpy);
93 * This method behaves mostly like MEDCouplingUMesh::deepCpy method, except that only nodal connectivity arrays are deeply copied.
94 * The coordinates are shared between \a this and the returned instance.
96 * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
97 * \sa MEDCouplingUMesh::deepCpy
99 MEDCouplingPointSet *MEDCouplingUMesh::deepCpyConnectivityOnly() const
101 checkConnectivityFullyDefined();
102 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=clone(false);
103 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(getNodalConnectivity()->deepCpy()),ci(getNodalConnectivityIndex()->deepCpy());
104 ret->setConnectivity(c,ci);
108 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other)
111 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
112 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
114 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
115 MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
116 setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
119 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
121 std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
125 std::vector<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildrenWithNull() const
127 std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildrenWithNull());
128 ret.push_back(_nodal_connec);
129 ret.push_back(_nodal_connec_index);
133 void MEDCouplingUMesh::updateTime() const
135 MEDCouplingPointSet::updateTime();
138 updateTimeWith(*_nodal_connec);
140 if(_nodal_connec_index)
142 updateTimeWith(*_nodal_connec_index);
146 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
151 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
152 * then \a this mesh is most probably is writable, exchangeable and available for most
153 * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
154 * this method to check that all is in order with \a this mesh.
155 * \throw If the mesh dimension is not set.
156 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
157 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
158 * \throw If the connectivity data array has more than one component.
159 * \throw If the connectivity data array has a named component.
160 * \throw If the connectivity index data array has more than one component.
161 * \throw If the connectivity index data array has a named component.
163 void MEDCouplingUMesh::checkCoherency() const
166 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
168 MEDCouplingPointSet::checkCoherency();
169 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
171 if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
173 std::ostringstream message;
174 message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
175 throw INTERP_KERNEL::Exception(message.str().c_str());
180 if(_nodal_connec->getNumberOfComponents()!=1)
181 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
182 if(_nodal_connec->getInfoOnComponent(0)!="")
183 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
187 throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
188 if(_nodal_connec_index)
190 if(_nodal_connec_index->getNumberOfComponents()!=1)
191 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
192 if(_nodal_connec_index->getInfoOnComponent(0)!="")
193 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
197 throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
201 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
202 * then \a this mesh is most probably is writable, exchangeable and available for all
203 * algorithms. <br> In addition to the checks performed by checkCoherency(), this
204 * method thoroughly checks the nodal connectivity.
205 * \param [in] eps - a not used parameter.
206 * \throw If the mesh dimension is not set.
207 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
208 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
209 * \throw If the connectivity data array has more than one component.
210 * \throw If the connectivity data array has a named component.
211 * \throw If the connectivity index data array has more than one component.
212 * \throw If the connectivity index data array has a named component.
213 * \throw If number of nodes defining an element does not correspond to the type of element.
214 * \throw If the nodal connectivity includes an invalid node id.
216 void MEDCouplingUMesh::checkCoherency1(double eps) const
221 int meshDim=getMeshDimension();
222 int nbOfNodes=getNumberOfNodes();
223 int nbOfCells=getNumberOfCells();
224 const int *ptr=_nodal_connec->getConstPointer();
225 const int *ptrI=_nodal_connec_index->getConstPointer();
226 for(int i=0;i<nbOfCells;i++)
228 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
229 if((int)cm.getDimension()!=meshDim)
231 std::ostringstream oss;
232 oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
233 throw INTERP_KERNEL::Exception(oss.str().c_str());
235 int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
237 if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
239 std::ostringstream oss;
240 oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " << cm.getNumberOfNodes();
241 oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
242 throw INTERP_KERNEL::Exception(oss.str().c_str());
244 for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
249 if(nodeId>=nbOfNodes)
251 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes !";
252 throw INTERP_KERNEL::Exception(oss.str().c_str());
257 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " in connectivity ! sounds bad !";
258 throw INTERP_KERNEL::Exception(oss.str().c_str());
262 if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
264 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #-1 in connectivity ! sounds bad !";
265 throw INTERP_KERNEL::Exception(oss.str().c_str());
274 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
275 * then \a this mesh is most probably is writable, exchangeable and available for all
276 * algorithms. <br> This method performs the same checks as checkCoherency1() does.
277 * \param [in] eps - a not used parameter.
278 * \throw If the mesh dimension is not set.
279 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
280 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
281 * \throw If the connectivity data array has more than one component.
282 * \throw If the connectivity data array has a named component.
283 * \throw If the connectivity index data array has more than one component.
284 * \throw If the connectivity index data array has a named component.
285 * \throw If number of nodes defining an element does not correspond to the type of element.
286 * \throw If the nodal connectivity includes an invalid node id.
288 void MEDCouplingUMesh::checkCoherency2(double eps) const
290 checkCoherency1(eps);
294 * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
295 * elements contained in the mesh. For more info on the mesh dimension see
296 * \ref MEDCouplingUMeshPage.
297 * \param [in] meshDim - a new mesh dimension.
298 * \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
300 void MEDCouplingUMesh::setMeshDimension(int meshDim)
302 if(meshDim<-1 || meshDim>3)
303 throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
309 * Allocates memory to store an estimation of the given number of cells. Closer is the estimation to the number of cells effectively inserted,
310 * less will be the needs to realloc. If the number of cells to be inserted is not known simply put 0 to this parameter.
311 * If a nodal connectivity previouly existed before the call of this method, it will be reset.
313 * \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
315 * \if ENABLE_EXAMPLES
316 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
317 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
320 void MEDCouplingUMesh::allocateCells(int nbOfCells)
323 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
324 if(_nodal_connec_index)
326 _nodal_connec_index->decrRef();
330 _nodal_connec->decrRef();
332 _nodal_connec_index=DataArrayInt::New();
333 _nodal_connec_index->reserve(nbOfCells+1);
334 _nodal_connec_index->pushBackSilent(0);
335 _nodal_connec=DataArrayInt::New();
336 _nodal_connec->reserve(2*nbOfCells);
342 * Appends a cell to the connectivity array. For deeper understanding what is
343 * happening see \ref MEDCouplingUMeshNodalConnectivity.
344 * \param [in] type - type of cell to add.
345 * \param [in] size - number of nodes constituting this cell.
346 * \param [in] nodalConnOfCell - the connectivity of the cell to add.
348 * \if ENABLE_EXAMPLES
349 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
350 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
353 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
355 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
356 if(_nodal_connec_index==0)
357 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
358 if((int)cm.getDimension()==_mesh_dim)
361 if(size!=(int)cm.getNumberOfNodes())
363 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
364 oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
365 throw INTERP_KERNEL::Exception(oss.str().c_str());
367 int idx=_nodal_connec_index->back();
369 _nodal_connec_index->pushBackSilent(val);
370 _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
375 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
376 oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
377 oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
378 throw INTERP_KERNEL::Exception(oss.str().c_str());
383 * Compacts data arrays to release unused memory. This method is to be called after
384 * finishing cell insertion using \a this->insertNextCell().
386 * \if ENABLE_EXAMPLES
387 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
388 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
391 void MEDCouplingUMesh::finishInsertingCells()
393 _nodal_connec->pack();
394 _nodal_connec_index->pack();
395 _nodal_connec->declareAsNew();
396 _nodal_connec_index->declareAsNew();
401 * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
402 * Useful for python users.
404 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
406 return new MEDCouplingUMeshCellIterator(this);
410 * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
411 * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
412 * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
413 * Useful for python users.
415 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
417 if(!checkConsecutiveCellTypes())
418 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
419 return new MEDCouplingUMeshCellByTypeEntry(this);
423 * Returns a set of all cell types available in \a this mesh.
424 * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
425 * \warning this method does not throw any exception even if \a this is not defined.
426 * \sa MEDCouplingUMesh::getAllGeoTypesSorted
428 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
434 * This method returns the sorted list of geometric types in \a this.
435 * Sorted means in the same order than the cells in \a this. A single entry in return vector means the maximal chunk of consecutive cells in \a this
436 * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
438 * \throw if connectivity in \a this is not correctly defined.
440 * \sa MEDCouplingMesh::getAllGeoTypes
442 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
444 std::vector<INTERP_KERNEL::NormalizedCellType> ret;
445 checkConnectivityFullyDefined();
446 int nbOfCells(getNumberOfCells());
449 if(getMeshLength()<1)
450 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
451 const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
452 ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
453 for(int i=1;i<nbOfCells;i++,ci++)
454 if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
455 ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
460 * This method is a method that compares \a this and \a other.
461 * This method compares \b all attributes, even names and component names.
463 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
466 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
467 std::ostringstream oss; oss.precision(15);
468 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
471 reason="mesh given in input is not castable in MEDCouplingUMesh !";
474 if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
476 if(_mesh_dim!=otherC->_mesh_dim)
478 oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" << otherC->_mesh_dim;
482 if(_types!=otherC->_types)
484 oss << "umesh geometric type mismatch :\nThis geometric types are :";
485 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
486 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
487 oss << "\nOther geometric types are :";
488 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
489 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
493 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
494 if(_nodal_connec==0 || otherC->_nodal_connec==0)
496 reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
499 if(_nodal_connec!=otherC->_nodal_connec)
500 if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
502 reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
505 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
506 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
508 reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
511 if(_nodal_connec_index!=otherC->_nodal_connec_index)
512 if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
514 reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
521 * Checks if data arrays of this mesh (node coordinates, nodal
522 * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
524 * \param [in] other - the mesh to compare with.
525 * \param [in] prec - precision value used to compare node coordinates.
526 * \return bool - \a true if the two meshes are same.
528 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
530 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
533 if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
535 if(_mesh_dim!=otherC->_mesh_dim)
537 if(_types!=otherC->_types)
539 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
540 if(_nodal_connec==0 || otherC->_nodal_connec==0)
542 if(_nodal_connec!=otherC->_nodal_connec)
543 if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
545 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
546 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
548 if(_nodal_connec_index!=otherC->_nodal_connec_index)
549 if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
555 * Checks if \a this and \a other meshes are geometrically equivalent with high
556 * probability, else an exception is thrown. The meshes are considered equivalent if
557 * (1) meshes contain the same number of nodes and the same number of elements of the
558 * same types (2) three cells of the two meshes (first, last and middle) are based
559 * on coincident nodes (with a specified precision).
560 * \param [in] other - the mesh to compare with.
561 * \param [in] prec - the precision used to compare nodes of the two meshes.
562 * \throw If the two meshes do not match.
564 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
566 MEDCouplingPointSet::checkFastEquivalWith(other,prec);
567 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
569 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !");
573 * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
574 * cells each node belongs to.
575 * \warning For speed reasons, this method does not check if node ids in the nodal
576 * connectivity correspond to the size of node coordinates array.
577 * \param [in,out] revNodal - an array holding ids of cells sharing each node.
578 * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
579 * dividing cell ids in \a revNodal into groups each referring to one
580 * node. Its every element (except the last one) is an index pointing to the
581 * first id of a group of cells. For example cells sharing the node #1 are
582 * described by following range of indices:
583 * [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
584 * \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
585 * Number of cells sharing the *i*-th node is
586 * \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
587 * \throw If the coordinates array is not set.
588 * \throw If the nodal connectivity of cells is not defined.
590 * \if ENABLE_EXAMPLES
591 * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
592 * \ref py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
595 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
598 int nbOfNodes=getNumberOfNodes();
599 int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
600 revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
601 std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
602 const int *conn=_nodal_connec->getConstPointer();
603 const int *connIndex=_nodal_connec_index->getConstPointer();
604 int nbOfCells=getNumberOfCells();
605 int nbOfEltsInRevNodal=0;
606 for(int eltId=0;eltId<nbOfCells;eltId++)
608 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
609 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
610 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
611 if(*iter>=0)//for polyhedrons
613 nbOfEltsInRevNodal++;
614 revNodalIndxPtr[(*iter)+1]++;
617 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
618 int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
619 revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
620 std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
621 for(int eltId=0;eltId<nbOfCells;eltId++)
623 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
624 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
625 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
626 if(*iter>=0)//for polyhedrons
627 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
633 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
638 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
644 if(cm.getOrientationStatus(nb,conn1,conn2))
651 class MinusOneSonsGenerator
654 MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
655 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
656 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
657 static const int DELTA=1;
659 const INTERP_KERNEL::CellModel& _cm;
662 class MinusOneSonsGeneratorBiQuadratic
665 MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
666 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
667 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
668 static const int DELTA=1;
670 const INTERP_KERNEL::CellModel& _cm;
673 class MinusTwoSonsGenerator
676 MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
677 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
678 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
679 static const int DELTA=2;
681 const INTERP_KERNEL::CellModel& _cm;
687 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
688 * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
689 * describing correspondence between cells of \a this and the result meshes are
690 * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
691 * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
692 * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
693 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
694 * \warning For speed reasons, this method does not check if node ids in the nodal
695 * connectivity correspond to the size of node coordinates array.
696 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
697 * to write this mesh to the MED file, its cells must be sorted using
698 * sortCellsInMEDFileFrmt().
699 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
700 * each cell of \a this mesh.
701 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
702 * dividing cell ids in \a desc into groups each referring to one
703 * cell of \a this mesh. Its every element (except the last one) is an index
704 * pointing to the first id of a group of cells. For example cells of the
705 * result mesh bounding the cell #1 of \a this mesh are described by following
707 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
708 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
709 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
710 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
711 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
712 * by each cell of the result mesh.
713 * \param [in,out] revDescIndx - the array, of length one more than number of cells
714 * in the result mesh,
715 * dividing cell ids in \a revDesc into groups each referring to one
716 * cell of the result mesh the same way as \a descIndx divides \a desc.
717 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
718 * delete this mesh using decrRef() as it is no more needed.
719 * \throw If the coordinates array is not set.
720 * \throw If the nodal connectivity of cells is node defined.
721 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
722 * revDescIndx == NULL.
724 * \if ENABLE_EXAMPLES
725 * \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
726 * \ref py_mcumesh_buildDescendingConnectivity "Here is a Python example".
728 * \sa buildDescendingConnectivity2()
730 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
732 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
736 * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
737 * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
738 * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
739 * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
740 * \sa MEDCouplingUMesh::buildDescendingConnectivity
742 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
745 if(getMeshDimension()!=3)
746 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
747 return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
751 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
752 * this->getMeshDimension(), that bound cells of \a this mesh. In
753 * addition arrays describing correspondence between cells of \a this and the result
754 * meshes are returned. The arrays \a desc and \a descIndx describe the descending
755 * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
756 * mesh. This method differs from buildDescendingConnectivity() in that apart
757 * from cell ids, \a desc returns mutual orientation of cells in \a this and the
758 * result meshes. So a positive id means that order of nodes in corresponding cells
759 * of two meshes is same, and a negative id means a reverse order of nodes. Since a
760 * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
761 * i.e. cell ids are one-based.
762 * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
763 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
764 * \warning For speed reasons, this method does not check if node ids in the nodal
765 * connectivity correspond to the size of node coordinates array.
766 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
767 * to write this mesh to the MED file, its cells must be sorted using
768 * sortCellsInMEDFileFrmt().
769 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
770 * each cell of \a this mesh.
771 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
772 * dividing cell ids in \a desc into groups each referring to one
773 * cell of \a this mesh. Its every element (except the last one) is an index
774 * pointing to the first id of a group of cells. For example cells of the
775 * result mesh bounding the cell #1 of \a this mesh are described by following
777 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
778 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
779 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
780 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
781 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
782 * by each cell of the result mesh.
783 * \param [in,out] revDescIndx - the array, of length one more than number of cells
784 * in the result mesh,
785 * dividing cell ids in \a revDesc into groups each referring to one
786 * cell of the result mesh the same way as \a descIndx divides \a desc.
787 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
788 * shares the node coordinates array with \a this mesh. The caller is to
789 * delete this mesh using decrRef() as it is no more needed.
790 * \throw If the coordinates array is not set.
791 * \throw If the nodal connectivity of cells is node defined.
792 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
793 * revDescIndx == NULL.
795 * \if ENABLE_EXAMPLES
796 * \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
797 * \ref py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
799 * \sa buildDescendingConnectivity()
801 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
803 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
807 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
808 * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
809 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
810 * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
812 * \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
813 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
814 * \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.
816 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
818 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
819 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
820 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
821 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
822 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
824 ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
828 * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
829 * 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,
830 * excluding a set of meshdim-1 cells in input descending connectivity.
831 * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
832 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
833 * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
835 * \param [in] desc descending connectivity array.
836 * \param [in] descIndx descending connectivity index array used to walk through \b desc.
837 * \param [in] revDesc reverse descending connectivity array.
838 * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
839 * \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
840 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
841 * \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.
843 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
844 DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx)
846 if(!desc || !descIndx || !revDesc || !revDescIndx)
847 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
848 const int *descPtr=desc->getConstPointer();
849 const int *descIPtr=descIndx->getConstPointer();
850 const int *revDescPtr=revDesc->getConstPointer();
851 const int *revDescIPtr=revDescIndx->getConstPointer();
853 int nbCells=descIndx->getNumberOfTuples()-1;
854 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
855 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
856 int *out1Ptr=out1->getPointer();
858 out0->reserve(desc->getNumberOfTuples());
859 for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
861 for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
863 std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
865 out0->insertAtTheEnd(s.begin(),s.end());
867 *out1Ptr=out0->getNumberOfTuples();
869 neighbors=out0.retn();
870 neighborsIndx=out1.retn();
874 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
875 * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
876 * This method lists node by node in \b this which are its neighbors. To compute the result only connectivities are considered.
877 * The neighbor nodes of node having id 'nodeId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
879 * \param [out] neighbors is an array storing all the neighbors of all nodes in \b this. This array is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
880 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
881 * \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.
883 void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayInt *&neighbors, DataArrayInt *&neighborsIdx) const
886 int mdim(getMeshDimension()),nbNodes(getNumberOfNodes());
887 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descIndx(DataArrayInt::New()),revDesc(DataArrayInt::New()),revDescIndx(DataArrayInt::New());
888 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh1D;
893 mesh1D=explode3DMeshTo1D(desc,descIndx,revDesc,revDescIndx);
898 mesh1D=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
903 mesh1D=const_cast<MEDCouplingUMesh *>(this);
909 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2,1] !");
912 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=0; revDescIndx=0;
913 mesh1D->getReverseNodalConnectivity(desc,descIndx);
914 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0(DataArrayInt::New());
915 ret0->alloc(desc->getNumberOfTuples(),1);
916 int *r0Pt(ret0->getPointer());
917 const int *c1DPtr(mesh1D->getNodalConnectivity()->begin()),*rn(desc->begin()),*rni(descIndx->begin());
918 for(int i=0;i<nbNodes;i++,rni++)
920 for(const int *oneDCellIt=rn+rni[0];oneDCellIt!=rn+rni[1];oneDCellIt++)
921 *r0Pt++=c1DPtr[3*(*oneDCellIt)+1]==i?c1DPtr[3*(*oneDCellIt)+2]:c1DPtr[3*(*oneDCellIt)+1];
923 neighbors=ret0.retn();
924 neighborsIdx=descIndx.retn();
930 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
931 * For speed reasons no check of this will be done.
933 template<class SonsGenerator>
934 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
936 if(!desc || !descIndx || !revDesc || !revDescIndx)
937 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
938 checkConnectivityFullyDefined();
939 int nbOfCells=getNumberOfCells();
940 int nbOfNodes=getNumberOfNodes();
941 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
942 int *revNodalIndxPtr=revNodalIndx->getPointer();
943 const int *conn=_nodal_connec->getConstPointer();
944 const int *connIndex=_nodal_connec_index->getConstPointer();
945 std::string name="Mesh constituent of "; name+=getName();
946 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA);
947 ret->setCoords(getCoords());
948 ret->allocateCells(2*nbOfCells);
949 descIndx->alloc(nbOfCells+1,1);
950 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
951 int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
952 for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
954 int pos=connIndex[eltId];
955 int posP1=connIndex[eltId+1];
956 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
957 SonsGenerator sg(cm);
958 unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
959 INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
960 for(unsigned i=0;i<nbOfSons;i++)
962 INTERP_KERNEL::NormalizedCellType cmsId;
963 unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
964 for(unsigned k=0;k<nbOfNodesSon;k++)
966 revNodalIndxPtr[tmp[k]+1]++;
967 ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
968 revDesc2->pushBackSilent(eltId);
970 descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
972 int nbOfCellsM1=ret->getNumberOfCells();
973 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
974 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
975 std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
976 int *revNodalPtr=revNodal->getPointer();
977 const int *connM1=ret->getNodalConnectivity()->getConstPointer();
978 const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
979 for(int eltId=0;eltId<nbOfCellsM1;eltId++)
981 const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
982 const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
983 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
984 if(*iter>=0)//for polyhedrons
985 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
988 DataArrayInt *commonCells=0,*commonCellsI=0;
989 FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
990 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
991 const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
992 int newNbOfCellsM1=-1;
993 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
994 commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
995 std::vector<bool> isImpacted(nbOfCellsM1,false);
996 for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
997 for(int work2=work[0];work2!=work[1];work2++)
998 isImpacted[commonCellsPtr[work2]]=true;
999 const int *o2nM1Ptr=o2nM1->getConstPointer();
1000 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
1001 const int *n2oM1Ptr=n2oM1->getConstPointer();
1002 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
1003 ret2->copyTinyInfoFrom(this);
1004 desc->alloc(descIndx->back(),1);
1005 int *descPtr=desc->getPointer();
1006 const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
1007 for(int i=0;i<nbOfCellsM1;i++,descPtr++)
1010 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1013 if(i!=n2oM1Ptr[o2nM1Ptr[i]])
1015 const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
1016 *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
1019 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1022 revDesc->reserve(newNbOfCellsM1);
1023 revDescIndx->alloc(newNbOfCellsM1+1,1);
1024 int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
1025 const int *revDesc2Ptr=revDesc2->getConstPointer();
1026 for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
1028 int oldCellIdM1=n2oM1Ptr[i];
1029 if(!isImpacted[oldCellIdM1])
1031 revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
1032 revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
1036 for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
1037 revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
1038 revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
1046 struct MEDCouplingAccVisit
1048 MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1049 int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1050 int _new_nb_of_nodes;
1056 * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1057 * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1058 * array of cell ids. Pay attention that after conversion all algorithms work slower
1059 * with \a this mesh than before conversion. <br> If an exception is thrown during the
1060 * conversion due presence of invalid ids in the array of cells to convert, as a
1061 * result \a this mesh contains some already converted elements. In this case the 2D
1062 * mesh remains valid but 3D mesh becomes \b inconsistent!
1063 * \warning This method can significantly modify the order of geometric types in \a this,
1064 * hence, to write this mesh to the MED file, its cells must be sorted using
1065 * sortCellsInMEDFileFrmt().
1066 * \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1067 * \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1068 * cellIdsToConvertBg.
1069 * \throw If the coordinates array is not set.
1070 * \throw If the nodal connectivity of cells is node defined.
1071 * \throw If dimension of \a this mesh is not either 2 or 3.
1073 * \if ENABLE_EXAMPLES
1074 * \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1075 * \ref py_mcumesh_convertToPolyTypes "Here is a Python example".
1078 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1080 checkFullyDefined();
1081 int dim=getMeshDimension();
1083 throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1084 int nbOfCells(getNumberOfCells());
1087 const int *connIndex=_nodal_connec_index->getConstPointer();
1088 int *conn=_nodal_connec->getPointer();
1089 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1091 if(*iter>=0 && *iter<nbOfCells)
1093 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1094 if(!cm.isQuadratic())
1095 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1097 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1101 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1102 oss << " in range [0," << nbOfCells << ") !";
1103 throw INTERP_KERNEL::Exception(oss.str().c_str());
1109 int *connIndex(_nodal_connec_index->getPointer());
1110 const int *connOld(_nodal_connec->getConstPointer());
1111 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1112 std::vector<bool> toBeDone(nbOfCells,false);
1113 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1115 if(*iter>=0 && *iter<nbOfCells)
1116 toBeDone[*iter]=true;
1119 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1120 oss << " in range [0," << nbOfCells << ") !";
1121 throw INTERP_KERNEL::Exception(oss.str().c_str());
1124 for(int cellId=0;cellId<nbOfCells;cellId++)
1126 int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1127 int lgthOld(posP1-pos-1);
1128 if(toBeDone[cellId])
1130 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1131 unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1132 int *tmp(new int[nbOfFaces*lgthOld+1]);
1133 int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1134 for(unsigned j=0;j<nbOfFaces;j++)
1136 INTERP_KERNEL::NormalizedCellType type;
1137 unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1141 std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1142 connNew->pushBackValsSilent(tmp,tmp+newLgth);
1143 connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1148 connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1149 connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1152 setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1158 * Converts all cells to either polygons (if \a this is a 2D mesh) or
1159 * polyhedrons (if \a this is a 3D mesh).
1160 * \warning As this method is purely for user-friendliness and no optimization is
1161 * done to avoid construction of a useless vector, this method can be costly
1163 * \throw If the coordinates array is not set.
1164 * \throw If the nodal connectivity of cells is node defined.
1165 * \throw If dimension of \a this mesh is not either 2 or 3.
1167 void MEDCouplingUMesh::convertAllToPoly()
1169 int nbOfCells=getNumberOfCells();
1170 std::vector<int> cellIds(nbOfCells);
1171 for(int i=0;i<nbOfCells;i++)
1173 convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1177 * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1178 * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1179 * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1180 * base facet of the volume and the second half of nodes describes an opposite facet
1181 * having the same number of nodes as the base one. This method converts such
1182 * connectivity to a valid polyhedral format where connectivity of each facet is
1183 * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1184 * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1185 * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1186 * a correct orientation of the first facet of a polyhedron, else orientation of a
1187 * corrected cell is reverse.<br>
1188 * This method is useful to build an extruded unstructured mesh with polyhedrons as
1189 * it releases the user from boring description of polyhedra connectivity in the valid
1191 * \throw If \a this->getMeshDimension() != 3.
1192 * \throw If \a this->getSpaceDimension() != 3.
1193 * \throw If the nodal connectivity of cells is not defined.
1194 * \throw If the coordinates array is not set.
1195 * \throw If \a this mesh contains polyhedrons with the valid connectivity.
1196 * \throw If \a this mesh contains polyhedrons with odd number of nodes.
1198 * \if ENABLE_EXAMPLES
1199 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1200 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1203 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1205 checkFullyDefined();
1206 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1207 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1208 int nbOfCells=getNumberOfCells();
1209 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1210 newCi->alloc(nbOfCells+1,1);
1211 int *newci=newCi->getPointer();
1212 const int *ci=_nodal_connec_index->getConstPointer();
1213 const int *c=_nodal_connec->getConstPointer();
1215 for(int i=0;i<nbOfCells;i++)
1217 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1218 if(type==INTERP_KERNEL::NORM_POLYHED)
1220 if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1222 std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1223 throw INTERP_KERNEL::Exception(oss.str().c_str());
1225 std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1228 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 !";
1229 throw INTERP_KERNEL::Exception(oss.str().c_str());
1232 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)
1235 newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1237 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1238 newC->alloc(newci[nbOfCells],1);
1239 int *newc=newC->getPointer();
1240 for(int i=0;i<nbOfCells;i++)
1242 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1243 if(type==INTERP_KERNEL::NORM_POLYHED)
1245 std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1246 newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1248 for(std::size_t j=0;j<n1;j++)
1250 newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1252 newc[n1+5*j+1]=c[ci[i]+1+j];
1253 newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1254 newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1255 newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1260 newc=std::copy(c+ci[i],c+ci[i+1],newc);
1262 _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1263 _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1268 * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1269 * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1270 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1271 * to write this mesh to the MED file, its cells must be sorted using
1272 * sortCellsInMEDFileFrmt().
1273 * \return \c true if at least one cell has been converted, \c false else. In the
1274 * last case the nodal connectivity remains unchanged.
1275 * \throw If the coordinates array is not set.
1276 * \throw If the nodal connectivity of cells is not defined.
1277 * \throw If \a this->getMeshDimension() < 0.
1279 bool MEDCouplingUMesh::unPolyze()
1281 checkFullyDefined();
1282 int mdim=getMeshDimension();
1284 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1287 int nbOfCells=getNumberOfCells();
1290 int initMeshLgth=getMeshLength();
1291 int *conn=_nodal_connec->getPointer();
1292 int *index=_nodal_connec_index->getPointer();
1297 for(int i=0;i<nbOfCells;i++)
1299 lgthOfCurCell=index[i+1]-posOfCurCell;
1300 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1301 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1302 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1306 switch(cm.getDimension())
1310 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1311 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1312 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1317 int nbOfFaces,lgthOfPolyhConn;
1318 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1319 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1324 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1328 ret=ret || (newType!=type);
1329 conn[newPos]=newType;
1331 posOfCurCell=index[i+1];
1336 std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1337 newPos+=lgthOfCurCell;
1338 posOfCurCell+=lgthOfCurCell;
1342 if(newPos!=initMeshLgth)
1343 _nodal_connec->reAlloc(newPos);
1350 * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1351 * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1352 * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells.
1354 * \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
1357 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1359 checkFullyDefined();
1360 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1361 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1362 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1363 coords->recenterForMaxPrecision(eps);
1365 int nbOfCells=getNumberOfCells();
1366 const int *conn=_nodal_connec->getConstPointer();
1367 const int *index=_nodal_connec_index->getConstPointer();
1368 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1369 connINew->alloc(nbOfCells+1,1);
1370 int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1371 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1373 for(int i=0;i<nbOfCells;i++,connINewPtr++)
1375 if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1377 SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1381 connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1382 *connINewPtr=connNew->getNumberOfTuples();
1385 setConnectivity(connNew,connINew,false);
1389 * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1390 * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1391 * the format of returned DataArrayInt instance.
1393 * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1394 * \sa MEDCouplingUMesh::getNodeIdsInUse
1396 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1398 checkConnectivityFullyDefined();
1399 int nbOfCells=getNumberOfCells();
1400 const int *connIndex=_nodal_connec_index->getConstPointer();
1401 const int *conn=_nodal_connec->getConstPointer();
1402 const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1403 int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1404 std::vector<bool> retS(maxElt,false);
1405 for(int i=0;i<nbOfCells;i++)
1406 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1410 for(int i=0;i<maxElt;i++)
1413 DataArrayInt *ret=DataArrayInt::New();
1415 int *retPtr=ret->getPointer();
1416 for(int i=0;i<maxElt;i++)
1423 * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1424 * \sa MEDCouplingUMesh::getNodeIdsInUse
1426 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1428 int nbOfNodes((int)nodeIdsInUse.size()),nbOfCells(getNumberOfCells());
1429 const int *connIndex(_nodal_connec_index->getConstPointer()),*conn(_nodal_connec->getConstPointer());
1430 for(int i=0;i<nbOfCells;i++)
1431 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1434 if(conn[j]<nbOfNodes)
1435 nodeIdsInUse[conn[j]]=true;
1438 std::ostringstream oss; oss << "MEDCouplingUMesh::computeNodeIdsAlg : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1439 throw INTERP_KERNEL::Exception(oss.str().c_str());
1445 * Finds nodes not used in any cell and returns an array giving a new id to every node
1446 * by excluding the unused nodes, for which the array holds -1. The result array is
1447 * a mapping in "Old to New" mode.
1448 * \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1449 * \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1450 * this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1451 * if the node is unused or a new id else. The caller is to delete this
1452 * array using decrRef() as it is no more needed.
1453 * \throw If the coordinates array is not set.
1454 * \throw If the nodal connectivity of cells is not defined.
1455 * \throw If the nodal connectivity includes an invalid id.
1457 * \if ENABLE_EXAMPLES
1458 * \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1459 * \ref py_mcumesh_getNodeIdsInUse "Here is a Python example".
1461 * \sa computeFetchedNodeIds, computeNodeIdsAlg()
1463 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1466 int nbOfNodes(getNumberOfNodes());
1467 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1468 ret->alloc(nbOfNodes,1);
1469 int *traducer=ret->getPointer();
1470 std::fill(traducer,traducer+nbOfNodes,-1);
1471 int nbOfCells=getNumberOfCells();
1472 const int *connIndex=_nodal_connec_index->getConstPointer();
1473 const int *conn=_nodal_connec->getConstPointer();
1474 for(int i=0;i<nbOfCells;i++)
1475 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1478 if(conn[j]<nbOfNodes)
1479 traducer[conn[j]]=1;
1482 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1483 throw INTERP_KERNEL::Exception(oss.str().c_str());
1486 nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1487 std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1492 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1493 * For each cell in \b this the number of nodes constituting cell is computed.
1494 * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1495 * So for pohyhedrons some nodes can be counted several times in the returned result.
1497 * \return a newly allocated array
1498 * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1500 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1502 checkConnectivityFullyDefined();
1503 int nbOfCells=getNumberOfCells();
1504 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1505 ret->alloc(nbOfCells,1);
1506 int *retPtr=ret->getPointer();
1507 const int *conn=getNodalConnectivity()->getConstPointer();
1508 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1509 for(int i=0;i<nbOfCells;i++,retPtr++)
1511 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1512 *retPtr=connI[i+1]-connI[i]-1;
1514 *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1520 * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1521 * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1523 * \return DataArrayInt * - new object to be deallocated by the caller.
1524 * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1526 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1528 checkConnectivityFullyDefined();
1529 int nbOfCells=getNumberOfCells();
1530 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1531 ret->alloc(nbOfCells,1);
1532 int *retPtr=ret->getPointer();
1533 const int *conn=getNodalConnectivity()->getConstPointer();
1534 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1535 for(int i=0;i<nbOfCells;i++,retPtr++)
1537 std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1538 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1539 *retPtr=(int)s.size();
1543 *retPtr=(int)s.size();
1550 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1551 * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1553 * \return a newly allocated array
1555 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1557 checkConnectivityFullyDefined();
1558 int nbOfCells=getNumberOfCells();
1559 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1560 ret->alloc(nbOfCells,1);
1561 int *retPtr=ret->getPointer();
1562 const int *conn=getNodalConnectivity()->getConstPointer();
1563 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1564 for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1566 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1567 *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1573 * Removes unused nodes (the node coordinates array is shorten) and returns an array
1574 * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1575 * array mean that the corresponding old node is no more used.
1576 * \return DataArrayInt * - a new instance of DataArrayInt of length \a
1577 * this->getNumberOfNodes() before call of this method. The caller is to
1578 * delete this array using decrRef() as it is no more needed.
1579 * \throw If the coordinates array is not set.
1580 * \throw If the nodal connectivity of cells is not defined.
1581 * \throw If the nodal connectivity includes an invalid id.
1583 * \if ENABLE_EXAMPLES
1584 * \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1585 * \ref py_mcumesh_zipCoordsTraducer "Here is a Python example".
1588 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1590 return MEDCouplingPointSet::zipCoordsTraducer();
1594 * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1595 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1597 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1602 return AreCellsEqual0(conn,connI,cell1,cell2);
1604 return AreCellsEqual1(conn,connI,cell1,cell2);
1606 return AreCellsEqual2(conn,connI,cell1,cell2);
1608 return AreCellsEqual3(conn,connI,cell1,cell2);
1610 return AreCellsEqual7(conn,connI,cell1,cell2);
1612 throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1616 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1618 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1620 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1621 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1626 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1628 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1630 int sz=connI[cell1+1]-connI[cell1];
1631 if(sz==connI[cell2+1]-connI[cell2])
1633 if(conn[connI[cell1]]==conn[connI[cell2]])
1635 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1636 unsigned dim=cm.getDimension();
1642 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1643 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1644 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1645 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1646 return work!=tmp+sz1?1:0;
1649 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1652 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1659 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1661 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1663 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1665 if(conn[connI[cell1]]==conn[connI[cell2]])
1667 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1668 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1676 * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1678 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1680 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1682 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1683 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1690 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1692 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1694 int sz=connI[cell1+1]-connI[cell1];
1695 if(sz==connI[cell2+1]-connI[cell2])
1697 if(conn[connI[cell1]]==conn[connI[cell2]])
1699 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1700 unsigned dim=cm.getDimension();
1706 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1707 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1708 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1709 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1714 std::reverse_iterator<int *> it1((int *)tmp+sz1);
1715 std::reverse_iterator<int *> it2((int *)tmp);
1716 if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1722 return work!=tmp+sz1?1:0;
1725 {//case of SEG2 and SEG3
1726 if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1728 if(!cm.isQuadratic())
1730 std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1731 std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1732 if(std::equal(it1,it2,conn+connI[cell2]+1))
1738 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])
1745 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1752 * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1753 * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1754 * and result remains unchanged.
1755 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1756 * If in 'candidates' pool -1 value is considered as an empty value.
1757 * WARNING this method returns only ONE set of result !
1759 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1761 if(candidates.size()<1)
1764 std::vector<int>::const_iterator iter=candidates.begin();
1765 int start=(*iter++);
1766 for(;iter!=candidates.end();iter++)
1768 int status=AreCellsEqual(conn,connI,start,*iter,compType);
1773 result->pushBackSilent(start);
1777 result->pushBackSilent(*iter);
1779 result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1786 * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1787 * This method keeps the coordiantes of \a this. This method is time consuming and is called
1789 * \param [in] compType input specifying the technique used to compare cells each other.
1790 * - 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.
1791 * - 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)
1792 * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1793 * - 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
1794 * can be used for users not sensitive to orientation of cell
1795 * \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.
1796 * \param [out] commonCells
1797 * \param [out] commonCellsI
1798 * \return the correspondance array old to new in a newly allocated array.
1801 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1803 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1804 getReverseNodalConnectivity(revNodal,revNodalI);
1805 FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1808 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1809 DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr)
1811 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1812 int nbOfCells=nodalI->getNumberOfTuples()-1;
1813 commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1814 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1815 const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1816 std::vector<bool> isFetched(nbOfCells,false);
1819 for(int i=0;i<nbOfCells;i++)
1823 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1824 std::vector<int> v,v2;
1825 if(connOfNode!=connPtr+connIPtr[i+1])
1827 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1828 v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1831 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1835 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1836 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1837 v2.resize(std::distance(v2.begin(),it));
1841 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1843 int pos=commonCellsI->back();
1844 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1845 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1846 isFetched[*it]=true;
1854 for(int i=startCellId;i<nbOfCells;i++)
1858 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1859 std::vector<int> v,v2;
1860 if(connOfNode!=connPtr+connIPtr[i+1])
1862 v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1865 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1869 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1870 v2.resize(std::distance(v2.begin(),it));
1874 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1876 int pos=commonCellsI->back();
1877 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1878 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1879 isFetched[*it]=true;
1885 commonCellsArr=commonCells.retn();
1886 commonCellsIArr=commonCellsI.retn();
1890 * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1891 * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1892 * than \a other->getNumberOfCells() in the returned array means that there is no
1893 * corresponding cell in \a this mesh.
1894 * It is expected that \a this and \a other meshes share the same node coordinates
1895 * array, if it is not so an exception is thrown.
1896 * \param [in] other - the mesh to compare with.
1897 * \param [in] compType - specifies a cell comparison technique. For meaning of its
1898 * valid values [0,1,2], see zipConnectivityTraducer().
1899 * \param [out] arr - a new instance of DataArrayInt returning correspondence
1900 * between cells of the two meshes. It contains \a other->getNumberOfCells()
1901 * values. The caller is to delete this array using
1902 * decrRef() as it is no more needed.
1903 * \return bool - \c true if all cells of \a other mesh are present in the \a this
1906 * \if ENABLE_EXAMPLES
1907 * \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1908 * \ref py_mcumesh_areCellsIncludedIn "Here is a Python example".
1910 * \sa checkDeepEquivalOnSameNodesWith()
1911 * \sa checkGeoEquivalWith()
1913 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1915 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1916 int nbOfCells=getNumberOfCells();
1917 static const int possibleCompType[]={0,1,2};
1918 if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1920 std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1921 std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1923 throw INTERP_KERNEL::Exception(oss.str().c_str());
1925 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1926 arr=o2n->substr(nbOfCells);
1927 arr->setName(other->getName());
1929 if(other->getNumberOfCells()==0)
1931 return arr->getMaxValue(tmp)<nbOfCells;
1935 * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1936 * This method tries to determine if \b other is fully included in \b this.
1937 * The main difference is that this method is not expected to throw exception.
1938 * This method has two outputs :
1940 * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1941 * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1943 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1945 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1946 DataArrayInt *commonCells=0,*commonCellsI=0;
1947 int thisNbCells=getNumberOfCells();
1948 mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1949 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1950 const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1951 int otherNbCells=other->getNumberOfCells();
1952 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1953 arr2->alloc(otherNbCells,1);
1954 arr2->fillWithZero();
1955 int *arr2Ptr=arr2->getPointer();
1956 int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1957 for(int i=0;i<nbOfCommon;i++)
1959 int start=commonCellsPtr[commonCellsIPtr[i]];
1960 if(start<thisNbCells)
1962 for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1964 int sig=commonCellsPtr[j]>0?1:-1;
1965 int val=std::abs(commonCellsPtr[j])-1;
1966 if(val>=thisNbCells)
1967 arr2Ptr[val-thisNbCells]=sig*(start+1);
1971 arr2->setName(other->getName());
1972 if(arr2->presenceOfValue(0))
1978 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1981 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1982 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1984 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1985 std::vector<const MEDCouplingUMesh *> ms(2);
1988 return MergeUMeshesOnSameCoords(ms);
1992 * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1993 * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1994 * cellIds is not given explicitely but by a range python like.
1996 * \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.
1997 * \return a newly allocated
1999 * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
2000 * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
2002 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const
2004 if(getMeshDimension()!=-1)
2005 return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
2008 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
2010 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2012 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2014 return const_cast<MEDCouplingUMesh *>(this);
2019 * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
2020 * The result mesh shares or not the node coordinates array with \a this mesh depending
2021 * on \a keepCoords parameter.
2022 * \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
2023 * to write this mesh to the MED file, its cells must be sorted using
2024 * sortCellsInMEDFileFrmt().
2025 * \param [in] begin - an array of cell ids to include to the new mesh.
2026 * \param [in] end - a pointer to last-plus-one-th element of \a begin.
2027 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2028 * array of \a this mesh, else "free" nodes are removed from the result mesh
2029 * by calling zipCoords().
2030 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2031 * to delete this mesh using decrRef() as it is no more needed.
2032 * \throw If the coordinates array is not set.
2033 * \throw If the nodal connectivity of cells is not defined.
2034 * \throw If any cell id in the array \a begin is not valid.
2036 * \if ENABLE_EXAMPLES
2037 * \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
2038 * \ref py_mcumesh_buildPartOfMySelf "Here is a Python example".
2041 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2043 if(getMeshDimension()!=-1)
2044 return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
2048 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2050 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2052 return const_cast<MEDCouplingUMesh *>(this);
2057 * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2059 * 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.
2060 * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2061 * The number of cells of \b this will remain the same with this method.
2063 * \param [in] begin begin of cell ids (included) of cells in this to assign
2064 * \param [in] end end of cell ids (excluded) of cells in this to assign
2065 * \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 ).
2066 * Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2068 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2070 checkConnectivityFullyDefined();
2071 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2072 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2073 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2074 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2076 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2077 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2078 throw INTERP_KERNEL::Exception(oss.str().c_str());
2080 int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2081 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2083 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2084 throw INTERP_KERNEL::Exception(oss.str().c_str());
2086 int nbOfCells=getNumberOfCells();
2087 bool easyAssign=true;
2088 const int *connI=_nodal_connec_index->getConstPointer();
2089 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2090 for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2092 if(*it>=0 && *it<nbOfCells)
2094 easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2098 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2099 throw INTERP_KERNEL::Exception(oss.str().c_str());
2104 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2109 DataArrayInt *arrOut=0,*arrIOut=0;
2110 MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2112 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2113 setConnectivity(arrOut,arrIOut,true);
2117 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2119 checkConnectivityFullyDefined();
2120 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2121 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2122 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2123 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2125 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2126 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2127 throw INTERP_KERNEL::Exception(oss.str().c_str());
2129 int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2130 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2132 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2133 throw INTERP_KERNEL::Exception(oss.str().c_str());
2135 int nbOfCells=getNumberOfCells();
2136 bool easyAssign=true;
2137 const int *connI=_nodal_connec_index->getConstPointer();
2138 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2140 for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2142 if(it>=0 && it<nbOfCells)
2144 easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2148 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2149 throw INTERP_KERNEL::Exception(oss.str().c_str());
2154 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2159 DataArrayInt *arrOut=0,*arrIOut=0;
2160 MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2162 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2163 setConnectivity(arrOut,arrIOut,true);
2168 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2169 * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2170 * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2171 * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2173 * \param [in] begin input start of array of node ids.
2174 * \param [in] end input end of array of node ids.
2175 * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2176 * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2178 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2180 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2181 checkConnectivityFullyDefined();
2183 int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2184 std::vector<bool> fastFinder(sz,false);
2185 for(const int *work=begin;work!=end;work++)
2186 if(*work>=0 && *work<sz)
2187 fastFinder[*work]=true;
2188 int nbOfCells=getNumberOfCells();
2189 const int *conn=getNodalConnectivity()->getConstPointer();
2190 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2191 for(int i=0;i<nbOfCells;i++)
2193 int ref=0,nbOfHit=0;
2194 for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2198 if(fastFinder[*work2])
2201 if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2202 cellIdsKept->pushBackSilent(i);
2204 cellIdsKeptArr=cellIdsKept.retn();
2208 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2209 * this->getMeshDimension(), that bound some cells of \a this mesh.
2210 * The cells of lower dimension to include to the result mesh are selected basing on
2211 * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2212 * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2213 * ==\c false, a cell is copied if any its node is in the array of node ids. The
2214 * created mesh shares the node coordinates array with \a this mesh.
2215 * \param [in] begin - the array of node ids.
2216 * \param [in] end - a pointer to the (last+1)-th element of \a begin.
2217 * \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2218 * array \a begin are added, else cells whose any node is in the
2219 * array \a begin are added.
2220 * \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2221 * to delete this mesh using decrRef() as it is no more needed.
2222 * \throw If the coordinates array is not set.
2223 * \throw If the nodal connectivity of cells is not defined.
2224 * \throw If any node id in \a begin is not valid.
2226 * \if ENABLE_EXAMPLES
2227 * \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2228 * \ref py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2231 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2233 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2234 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2235 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2236 desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2237 return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2241 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2242 * this->getMeshDimension(), which bound only one cell of \a this mesh.
2243 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2244 * array of \a this mesh, else "free" nodes are removed from the result mesh
2245 * by calling zipCoords().
2246 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2247 * to delete this mesh using decrRef() as it is no more needed.
2248 * \throw If the coordinates array is not set.
2249 * \throw If the nodal connectivity of cells is not defined.
2251 * \if ENABLE_EXAMPLES
2252 * \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2253 * \ref py_mcumesh_buildBoundaryMesh "Here is a Python example".
2256 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2258 DataArrayInt *desc=DataArrayInt::New();
2259 DataArrayInt *descIndx=DataArrayInt::New();
2260 DataArrayInt *revDesc=DataArrayInt::New();
2261 DataArrayInt *revDescIndx=DataArrayInt::New();
2263 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2266 descIndx->decrRef();
2267 int nbOfCells=meshDM1->getNumberOfCells();
2268 const int *revDescIndxC=revDescIndx->getConstPointer();
2269 std::vector<int> boundaryCells;
2270 for(int i=0;i<nbOfCells;i++)
2271 if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2272 boundaryCells.push_back(i);
2273 revDescIndx->decrRef();
2274 MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2279 * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2280 * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2281 * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown.
2283 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2285 checkFullyDefined();
2286 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2287 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2288 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2289 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2291 buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2292 desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2294 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2295 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2296 const int *revDescPtr=revDesc->getConstPointer();
2297 const int *revDescIndxPtr=revDescIndx->getConstPointer();
2298 int nbOfCells=getNumberOfCells();
2299 std::vector<bool> ret1(nbOfCells,false);
2301 for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2302 if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2303 { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2305 DataArrayInt *ret2=DataArrayInt::New();
2307 int *ret2Ptr=ret2->getPointer();
2309 for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2312 ret2->setName("BoundaryCells");
2317 * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2318 * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2319 * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2320 * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2322 * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2323 * This method method returns cells ids set s = s1 + s2 where :
2325 * - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2326 * - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2328 * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2329 * are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2331 * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2332 * \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
2333 * cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2335 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2337 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2338 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2339 checkConnectivityFullyDefined();
2340 otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2341 if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2342 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2343 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2344 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2345 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2346 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2347 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2348 const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2349 DataArrayInt *idsOtherInConsti=0;
2350 bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2351 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2353 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2355 for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2356 s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2357 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2358 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2359 DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2360 ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2361 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2362 ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2363 neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2364 RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2365 neighThisPartAuto=0;
2366 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2367 const int li[2]={0,1};
2368 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2369 s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2370 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2373 cellIdsRk0=s0arr.retn();
2374 cellIdsRk1=s_renum1.retn();
2378 * 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
2379 * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2381 * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2383 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2385 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2386 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2387 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2388 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2390 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2391 revDesc=0; desc=0; descIndx=0;
2392 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2393 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2394 return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2398 * Finds nodes lying on the boundary of \a this mesh.
2399 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2400 * nodes. The caller is to delete this array using decrRef() as it is no
2402 * \throw If the coordinates array is not set.
2403 * \throw If the nodal connectivity of cells is node defined.
2405 * \if ENABLE_EXAMPLES
2406 * \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2407 * \ref py_mcumesh_findBoundaryNodes "Here is a Python example".
2410 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2412 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2413 return skin->computeFetchedNodeIds();
2416 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2419 return const_cast<MEDCouplingUMesh *>(this);
2423 * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2424 * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2425 * 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.
2426 * 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.
2427 * 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.
2429 * \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
2430 * parameter is altered during the call.
2431 * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2432 * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2433 * \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.
2435 * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2437 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2438 DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const
2440 checkFullyDefined();
2441 otherDimM1OnSameCoords.checkFullyDefined();
2442 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2443 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2444 if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2445 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2446 DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2447 findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2448 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2449 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2450 s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2451 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2452 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2453 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2454 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2455 cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2457 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2458 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2459 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2460 DataArrayInt *idsTmp=0;
2461 bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2462 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2464 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2465 MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2466 DataArrayInt *tmp0=0,*tmp1=0;
2467 ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2468 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2469 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2470 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2471 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2472 cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2473 cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2475 cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2476 cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2477 nodeIdsToDuplicate=s3.retn();
2481 * This method operates a modification of the connectivity and coords in \b this.
2482 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2483 * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2484 * 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
2485 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2486 * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2488 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2490 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2491 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2493 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2495 int nbOfNodes=getNumberOfNodes();
2496 duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2497 duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2501 * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of
2502 * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range !
2504 * \param [in] offset - specifies the offset to be applied on each element of connectivity.
2506 * \sa renumberNodesInConn
2508 void MEDCouplingUMesh::renumberNodesWithOffsetInConn(int offset)
2510 checkConnectivityFullyDefined();
2511 int *conn(getNodalConnectivity()->getPointer());
2512 const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2513 int nbOfCells(getNumberOfCells());
2514 for(int i=0;i<nbOfCells;i++)
2515 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2517 int& node=conn[iconn];
2518 if(node>=0)//avoid polyhedron separator
2523 _nodal_connec->declareAsNew();
2528 * Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
2529 * of array. This method is dedicated for renumbering from a big set of nodes the a tiny set of nodes which is the case during extraction
2532 void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& newNodeNumbersO2N)
2534 checkConnectivityFullyDefined();
2535 int *conn(getNodalConnectivity()->getPointer());
2536 const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2537 int nbOfCells(getNumberOfCells());
2538 for(int i=0;i<nbOfCells;i++)
2539 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2541 int& node=conn[iconn];
2542 if(node>=0)//avoid polyhedron separator
2544 INTERP_KERNEL::HashMap<int,int>::const_iterator it(newNodeNumbersO2N.find(node));
2545 if(it!=newNodeNumbersO2N.end())
2551 std::ostringstream oss; oss << "MEDCouplingUMesh::renumberNodesInConn(map) : presence in connectivity for cell #" << i << " of node #" << node << " : Not in map !";
2552 throw INTERP_KERNEL::Exception(oss.str().c_str());
2556 _nodal_connec->declareAsNew();
2561 * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2562 * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2563 * This method is a generalization of shiftNodeNumbersInConn().
2564 * \warning This method performs no check of validity of new ids. **Use it with care !**
2565 * \param [in] newNodeNumbersO2N - a permutation array, of length \a
2566 * this->getNumberOfNodes(), in "Old to New" mode.
2567 * See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2568 * \throw If the nodal connectivity of cells is not defined.
2570 * \if ENABLE_EXAMPLES
2571 * \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2572 * \ref py_mcumesh_renumberNodesInConn "Here is a Python example".
2575 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2577 checkConnectivityFullyDefined();
2578 int *conn=getNodalConnectivity()->getPointer();
2579 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2580 int nbOfCells(getNumberOfCells());
2581 for(int i=0;i<nbOfCells;i++)
2582 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2584 int& node=conn[iconn];
2585 if(node>=0)//avoid polyhedron separator
2587 node=newNodeNumbersO2N[node];
2590 _nodal_connec->declareAsNew();
2595 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2596 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2597 * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2599 * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2601 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2603 checkConnectivityFullyDefined();
2604 int *conn=getNodalConnectivity()->getPointer();
2605 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2606 int nbOfCells=getNumberOfCells();
2607 for(int i=0;i<nbOfCells;i++)
2608 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2610 int& node=conn[iconn];
2611 if(node>=0)//avoid polyhedron separator
2616 _nodal_connec->declareAsNew();
2621 * This method operates a modification of the connectivity in \b this.
2622 * 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.
2623 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2624 * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2625 * 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
2626 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2627 * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2629 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2630 * As an another consequense after the call of this method \b this can be transiently non cohrent.
2632 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2633 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2634 * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ).
2636 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2638 checkConnectivityFullyDefined();
2639 std::map<int,int> m;
2641 for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2643 int *conn=getNodalConnectivity()->getPointer();
2644 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2645 int nbOfCells=getNumberOfCells();
2646 for(int i=0;i<nbOfCells;i++)
2647 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2649 int& node=conn[iconn];
2650 if(node>=0)//avoid polyhedron separator
2652 std::map<int,int>::iterator it=m.find(node);
2661 * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2663 * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2664 * After the call of this method the number of cells remains the same as before.
2666 * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2667 * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2668 * be strictly in [0;this->getNumberOfCells()).
2670 * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2671 * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2672 * should be contained in[0;this->getNumberOfCells()).
2674 * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2676 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2678 checkConnectivityFullyDefined();
2679 int nbCells=getNumberOfCells();
2680 const int *array=old2NewBg;
2682 array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2684 const int *conn=_nodal_connec->getConstPointer();
2685 const int *connI=_nodal_connec_index->getConstPointer();
2686 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2687 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2688 const int *n2oPtr=n2o->begin();
2689 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2690 newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2691 newConn->copyStringInfoFrom(*_nodal_connec);
2692 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2693 newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2694 newConnI->copyStringInfoFrom(*_nodal_connec_index);
2696 int *newC=newConn->getPointer();
2697 int *newCI=newConnI->getPointer();
2700 for(int i=0;i<nbCells;i++)
2703 int nbOfElts=connI[pos+1]-connI[pos];
2704 newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2709 setConnectivity(newConn,newConnI);
2711 free(const_cast<int *>(array));
2715 * Finds cells whose bounding boxes intersect a given bounding box.
2716 * \param [in] bbox - an array defining the bounding box via coordinates of its
2717 * extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2719 * \param [in] eps - a factor used to increase size of the bounding box of cell
2720 * before comparing it with \a bbox. This factor is multiplied by the maximal
2721 * extent of the bounding box of cell to produce an addition to this bounding box.
2722 * \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2723 * cells. The caller is to delete this array using decrRef() as it is no more
2725 * \throw If the coordinates array is not set.
2726 * \throw If the nodal connectivity of cells is not defined.
2728 * \if ENABLE_EXAMPLES
2729 * \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2730 * \ref py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2733 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2735 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2736 if(getMeshDimension()==-1)
2738 elems->pushBackSilent(0);
2739 return elems.retn();
2741 int dim=getSpaceDimension();
2742 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2743 const int* conn = getNodalConnectivity()->getConstPointer();
2744 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2745 const double* coords = getCoords()->getConstPointer();
2746 int nbOfCells=getNumberOfCells();
2747 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2749 for (int i=0; i<dim; i++)
2751 elem_bb[i*2]=std::numeric_limits<double>::max();
2752 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2755 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2757 int node= conn[inode];
2758 if(node>=0)//avoid polyhedron separator
2760 for (int idim=0; idim<dim; idim++)
2762 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2764 elem_bb[idim*2] = coords[node*dim+idim] ;
2766 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2768 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2773 if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2774 elems->pushBackSilent(ielem);
2776 return elems.retn();
2780 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2781 * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2782 * added in 'elems' parameter.
2784 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2786 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2787 if(getMeshDimension()==-1)
2789 elems->pushBackSilent(0);
2790 return elems.retn();
2792 int dim=getSpaceDimension();
2793 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2794 const int* conn = getNodalConnectivity()->getConstPointer();
2795 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2796 const double* coords = getCoords()->getConstPointer();
2797 int nbOfCells=getNumberOfCells();
2798 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2800 for (int i=0; i<dim; i++)
2802 elem_bb[i*2]=std::numeric_limits<double>::max();
2803 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2806 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2808 int node= conn[inode];
2809 if(node>=0)//avoid polyhedron separator
2811 for (int idim=0; idim<dim; idim++)
2813 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2815 elem_bb[idim*2] = coords[node*dim+idim] ;
2817 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2819 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2824 if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2825 elems->pushBackSilent(ielem);
2827 return elems.retn();
2831 * Returns a type of a cell by its id.
2832 * \param [in] cellId - the id of the cell of interest.
2833 * \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2834 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2836 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2838 const int *ptI=_nodal_connec_index->getConstPointer();
2839 const int *pt=_nodal_connec->getConstPointer();
2840 if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2841 return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2844 std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2845 throw INTERP_KERNEL::Exception(oss.str().c_str());
2850 * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2851 * This method does not throw exception if geometric type \a type is not in \a this.
2852 * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2853 * The coordinates array is not considered here.
2855 * \param [in] type the geometric type
2856 * \return cell ids in this having geometric type \a type.
2858 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2861 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2863 checkConnectivityFullyDefined();
2864 int nbCells=getNumberOfCells();
2865 int mdim=getMeshDimension();
2866 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2867 if(mdim!=(int)cm.getDimension())
2868 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2869 const int *ptI=_nodal_connec_index->getConstPointer();
2870 const int *pt=_nodal_connec->getConstPointer();
2871 for(int i=0;i<nbCells;i++)
2873 if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2874 ret->pushBackSilent(i);
2880 * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2882 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2884 const int *ptI=_nodal_connec_index->getConstPointer();
2885 const int *pt=_nodal_connec->getConstPointer();
2886 int nbOfCells=getNumberOfCells();
2888 for(int i=0;i<nbOfCells;i++)
2889 if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2895 * Returns the nodal connectivity of a given cell.
2896 * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2897 * all returned node ids can be used in getCoordinatesOfNode().
2898 * \param [in] cellId - an id of the cell of interest.
2899 * \param [in,out] conn - a vector where the node ids are appended. It is not
2900 * cleared before the appending.
2901 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2903 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2905 const int *ptI=_nodal_connec_index->getConstPointer();
2906 const int *pt=_nodal_connec->getConstPointer();
2907 for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2912 std::string MEDCouplingUMesh::simpleRepr() const
2914 static const char msg0[]="No coordinates specified !";
2915 std::ostringstream ret;
2916 ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2917 ret << "Description of mesh : \"" << getDescription() << "\"\n";
2919 double tt=getTime(tmpp1,tmpp2);
2920 ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2921 ret << "Iteration : " << tmpp1 << " Order : " << tmpp2 << "\n";
2923 { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2925 { ret << " Mesh dimension has not been set or is invalid !"; }
2928 const int spaceDim=getSpaceDimension();
2929 ret << spaceDim << "\nInfo attached on space dimension : ";
2930 for(int i=0;i<spaceDim;i++)
2931 ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2935 ret << msg0 << "\n";
2936 ret << "Number of nodes : ";
2938 ret << getNumberOfNodes() << "\n";
2940 ret << msg0 << "\n";
2941 ret << "Number of cells : ";
2942 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2943 ret << getNumberOfCells() << "\n";
2945 ret << "No connectivity specified !" << "\n";
2946 ret << "Cell types present : ";
2947 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2949 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2950 ret << cm.getRepr() << " ";
2956 std::string MEDCouplingUMesh::advancedRepr() const
2958 std::ostringstream ret;
2959 ret << simpleRepr();
2960 ret << "\nCoordinates array : \n___________________\n\n";
2962 _coords->reprWithoutNameStream(ret);
2964 ret << "No array set !\n";
2965 ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2966 reprConnectivityOfThisLL(ret);
2971 * This method returns a C++ code that is a dump of \a this.
2972 * This method will throw if this is not fully defined.
2974 std::string MEDCouplingUMesh::cppRepr() const
2976 static const char coordsName[]="coords";
2977 static const char connName[]="conn";
2978 static const char connIName[]="connI";
2979 checkFullyDefined();
2980 std::ostringstream ret; ret << "// coordinates" << std::endl;
2981 _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2982 _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2983 _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2984 ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2985 ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2986 ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2987 ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2991 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2993 std::ostringstream ret;
2994 reprConnectivityOfThisLL(ret);
2999 * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
3000 * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
3001 * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
3004 * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
3005 * 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
3006 * with number of tuples set to 0, if not the array is taken as this in the returned instance.
3008 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
3010 int mdim=getMeshDimension();
3012 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
3013 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
3014 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
3015 bool needToCpyCT=true;
3018 tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
3026 if(!_nodal_connec_index)
3028 tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
3033 tmp2=_nodal_connec_index;
3036 ret->setConnectivity(tmp1,tmp2,false);
3041 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
3042 ret->setCoords(coords);
3045 ret->setCoords(_coords);
3049 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
3051 if(_nodal_connec!=0 && _nodal_connec_index!=0)
3053 int nbOfCells=getNumberOfCells();
3054 const int *c=_nodal_connec->getConstPointer();
3055 const int *ci=_nodal_connec_index->getConstPointer();
3056 for(int i=0;i<nbOfCells;i++)
3058 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3059 stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3060 std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3065 stream << "Connectivity not defined !\n";
3068 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3070 const int *ptI=_nodal_connec_index->getConstPointer();
3071 const int *pt=_nodal_connec->getConstPointer();
3072 if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3073 return ptI[cellId+1]-ptI[cellId]-1;
3075 return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3079 * Returns types of cells of the specified part of \a this mesh.
3080 * This method avoids computing sub-mesh explicitely to get its types.
3081 * \param [in] begin - an array of cell ids of interest.
3082 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3083 * \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3084 * describing the cell types.
3085 * \throw If the coordinates array is not set.
3086 * \throw If the nodal connectivity of cells is not defined.
3087 * \sa getAllGeoTypes()
3089 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3091 checkFullyDefined();
3092 std::set<INTERP_KERNEL::NormalizedCellType> ret;
3093 const int *conn=_nodal_connec->getConstPointer();
3094 const int *connIndex=_nodal_connec_index->getConstPointer();
3095 for(const int *w=begin;w!=end;w++)
3096 ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3101 * Defines the nodal connectivity using given connectivity arrays. Optionally updates
3102 * a set of types of cells constituting \a this mesh.
3103 * This method is for advanced users having prepared their connectivity before. For
3104 * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3105 * \param [in] conn - the nodal connectivity array.
3106 * \param [in] connIndex - the nodal connectivity index array.
3107 * \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3110 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3112 DataArrayInt::SetArrayIn(conn,_nodal_connec);
3113 DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3114 if(isComputingTypes)
3120 * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
3121 * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3123 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3124 _nodal_connec(0),_nodal_connec_index(0),
3125 _types(other._types)
3127 if(other._nodal_connec)
3128 _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3129 if(other._nodal_connec_index)
3130 _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3133 MEDCouplingUMesh::~MEDCouplingUMesh()
3136 _nodal_connec->decrRef();
3137 if(_nodal_connec_index)
3138 _nodal_connec_index->decrRef();
3142 * Recomputes a set of cell types of \a this mesh. For more info see
3143 * \ref MEDCouplingUMeshNodalConnectivity.
3145 void MEDCouplingUMesh::computeTypes()
3147 if(_nodal_connec && _nodal_connec_index)
3150 const int *conn=_nodal_connec->getConstPointer();
3151 const int *connIndex=_nodal_connec_index->getConstPointer();
3152 int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
3154 for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
3155 _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
3160 * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3162 void MEDCouplingUMesh::checkFullyDefined() const
3164 if(!_nodal_connec_index || !_nodal_connec || !_coords)
3165 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3169 * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3171 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3173 if(!_nodal_connec_index || !_nodal_connec)
3174 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3178 * Returns a number of cells constituting \a this mesh.
3179 * \return int - the number of cells in \a this mesh.
3180 * \throw If the nodal connectivity of cells is not defined.
3182 int MEDCouplingUMesh::getNumberOfCells() const
3184 if(_nodal_connec_index)
3185 return _nodal_connec_index->getNumberOfTuples()-1;
3190 throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3194 * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3195 * mesh. For more info see \ref MEDCouplingMeshesPage.
3196 * \return int - the dimension of \a this mesh.
3197 * \throw If the mesh dimension is not defined using setMeshDimension().
3199 int MEDCouplingUMesh::getMeshDimension() const
3202 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3207 * Returns a length of the nodal connectivity array.
3208 * This method is for test reason. Normally the integer returned is not useable by
3209 * user. For more info see \ref MEDCouplingUMeshNodalConnectivity.
3210 * \return int - the length of the nodal connectivity array.
3212 int MEDCouplingUMesh::getMeshLength() const
3214 return _nodal_connec->getNbOfElems();
3218 * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3220 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3222 MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3223 tinyInfo.push_back(getMeshDimension());
3224 tinyInfo.push_back(getNumberOfCells());
3226 tinyInfo.push_back(getMeshLength());
3228 tinyInfo.push_back(-1);
3232 * First step of unserialization process.
3234 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3236 return tinyInfo[6]<=0;
3240 * Second step of serialization process.
3241 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3243 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3245 MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3247 a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3251 * Third and final step of serialization process.
3253 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3255 MEDCouplingPointSet::serialize(a1,a2);
3256 if(getMeshDimension()>-1)
3258 a1=DataArrayInt::New();
3259 a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3260 int *ptA1=a1->getPointer();
3261 const int *conn=getNodalConnectivity()->getConstPointer();
3262 const int *index=getNodalConnectivityIndex()->getConstPointer();
3263 ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3264 std::copy(conn,conn+getMeshLength(),ptA1);
3271 * Second and final unserialization process.
3272 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3274 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3276 MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3277 setMeshDimension(tinyInfo[5]);
3281 const int *recvBuffer=a1->getConstPointer();
3282 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3283 myConnecIndex->alloc(tinyInfo[6]+1,1);
3284 std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3285 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3286 myConnec->alloc(tinyInfo[7],1);
3287 std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3288 setConnectivity(myConnec, myConnecIndex);
3293 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3294 * CellIds are given using range specified by a start an end and step.
3296 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3298 checkFullyDefined();
3299 int ncell=getNumberOfCells();
3300 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3301 ret->_mesh_dim=_mesh_dim;
3302 ret->setCoords(_coords);
3303 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3304 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3305 int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3307 const int *conn=_nodal_connec->getConstPointer();
3308 const int *connIndex=_nodal_connec_index->getConstPointer();
3309 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3311 if(work>=0 && work<ncell)
3313 newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3317 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3318 throw INTERP_KERNEL::Exception(oss.str().c_str());
3321 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3322 int *newConnPtr=newConn->getPointer();
3323 std::set<INTERP_KERNEL::NormalizedCellType> types;
3325 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3327 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3328 newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3330 ret->setConnectivity(newConn,newConnI,false);
3332 ret->copyTinyInfoFrom(this);
3337 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3338 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3339 * The return newly allocated mesh will share the same coordinates as \a this.
3341 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3343 checkConnectivityFullyDefined();
3344 int ncell=getNumberOfCells();
3345 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3346 ret->_mesh_dim=_mesh_dim;
3347 ret->setCoords(_coords);
3348 std::size_t nbOfElemsRet=std::distance(begin,end);
3349 int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3351 const int *conn=_nodal_connec->getConstPointer();
3352 const int *connIndex=_nodal_connec_index->getConstPointer();
3354 for(const int *work=begin;work!=end;work++,newNbring++)
3356 if(*work>=0 && *work<ncell)
3357 connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3361 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3362 throw INTERP_KERNEL::Exception(oss.str().c_str());
3365 int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3366 int *connRetWork=connRet;
3367 std::set<INTERP_KERNEL::NormalizedCellType> types;
3368 for(const int *work=begin;work!=end;work++)
3370 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3371 connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3373 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3374 connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3375 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3376 connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3377 ret->setConnectivity(connRetArr,connIndexRetArr,false);
3379 ret->copyTinyInfoFrom(this);
3384 * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3386 * For 1D cells, the returned field contains lengths.<br>
3387 * For 2D cells, the returned field contains areas.<br>
3388 * For 3D cells, the returned field contains volumes.
3389 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3390 * orientation, i.e. the volume is always positive.
3391 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3392 * and one time . The caller is to delete this field using decrRef() as it is no
3395 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3397 std::string name="MeasureOfMesh_";
3399 int nbelem=getNumberOfCells();
3400 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3401 field->setName(name);
3402 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3403 array->alloc(nbelem,1);
3404 double *area_vol=array->getPointer();
3405 field->setArray(array) ; array=0;
3406 field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3407 field->synchronizeTimeWithMesh();
3408 if(getMeshDimension()!=-1)
3411 INTERP_KERNEL::NormalizedCellType type;
3412 int dim_space=getSpaceDimension();
3413 const double *coords=getCoords()->getConstPointer();
3414 const int *connec=getNodalConnectivity()->getConstPointer();
3415 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3416 for(int iel=0;iel<nbelem;iel++)
3418 ipt=connec_index[iel];
3419 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3420 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);
3423 std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3427 area_vol[0]=std::numeric_limits<double>::max();
3429 return field.retn();
3433 * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3435 * For 1D cells, the returned array contains lengths.<br>
3436 * For 2D cells, the returned array contains areas.<br>
3437 * For 3D cells, the returned array contains volumes.
3438 * This method avoids building explicitly a part of \a this mesh to perform the work.
3439 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3440 * orientation, i.e. the volume is always positive.
3441 * \param [in] begin - an array of cell ids of interest.
3442 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3443 * \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3444 * delete this array using decrRef() as it is no more needed.
3446 * \if ENABLE_EXAMPLES
3447 * \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3448 * \ref py_mcumesh_getPartMeasureField "Here is a Python example".
3450 * \sa getMeasureField()
3452 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3454 std::string name="PartMeasureOfMesh_";
3456 int nbelem=(int)std::distance(begin,end);
3457 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3458 array->setName(name);
3459 array->alloc(nbelem,1);
3460 double *area_vol=array->getPointer();
3461 if(getMeshDimension()!=-1)
3464 INTERP_KERNEL::NormalizedCellType type;
3465 int dim_space=getSpaceDimension();
3466 const double *coords=getCoords()->getConstPointer();
3467 const int *connec=getNodalConnectivity()->getConstPointer();
3468 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3469 for(const int *iel=begin;iel!=end;iel++)
3471 ipt=connec_index[*iel];
3472 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3473 *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3476 std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3480 area_vol[0]=std::numeric_limits<double>::max();
3482 return array.retn();
3486 * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3487 * \a this one. The returned field contains the dual cell volume for each corresponding
3488 * node in \a this mesh. In other words, the field returns the getMeasureField() of
3489 * the dual mesh in P1 sens of \a this.<br>
3490 * For 1D cells, the returned field contains lengths.<br>
3491 * For 2D cells, the returned field contains areas.<br>
3492 * For 3D cells, the returned field contains volumes.
3493 * This method is useful to check "P1*" conservative interpolators.
3494 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3495 * orientation, i.e. the volume is always positive.
3496 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3497 * nodes and one time. The caller is to delete this array using decrRef() as
3498 * it is no more needed.
3500 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3502 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3503 std::string name="MeasureOnNodeOfMesh_";
3505 int nbNodes=getNumberOfNodes();
3506 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3507 double cst=1./((double)getMeshDimension()+1.);
3508 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3509 array->alloc(nbNodes,1);
3510 double *valsToFill=array->getPointer();
3511 std::fill(valsToFill,valsToFill+nbNodes,0.);
3512 const double *values=tmp->getArray()->getConstPointer();
3513 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3514 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3515 getReverseNodalConnectivity(da,daInd);
3516 const int *daPtr=da->getConstPointer();
3517 const int *daIPtr=daInd->getConstPointer();
3518 for(int i=0;i<nbNodes;i++)
3519 for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3520 valsToFill[i]+=cst*values[*cell];
3522 ret->setArray(array);
3527 * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3528 * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3529 * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3530 * and are normalized.
3531 * <br> \a this can be either
3532 * - a 2D mesh in 2D or 3D space or
3533 * - an 1D mesh in 2D space.
3535 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3536 * cells and one time. The caller is to delete this field using decrRef() as
3537 * it is no more needed.
3538 * \throw If the nodal connectivity of cells is not defined.
3539 * \throw If the coordinates array is not set.
3540 * \throw If the mesh dimension is not set.
3541 * \throw If the mesh and space dimension is not as specified above.
3543 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3545 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3546 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3547 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3548 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3549 int nbOfCells=getNumberOfCells();
3550 int nbComp=getMeshDimension()+1;
3551 array->alloc(nbOfCells,nbComp);
3552 double *vals=array->getPointer();
3553 const int *connI=_nodal_connec_index->getConstPointer();
3554 const int *conn=_nodal_connec->getConstPointer();
3555 const double *coords=_coords->getConstPointer();
3556 if(getMeshDimension()==2)
3558 if(getSpaceDimension()==3)
3560 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3561 const double *locPtr=loc->getConstPointer();
3562 for(int i=0;i<nbOfCells;i++,vals+=3)
3564 int offset=connI[i];
3565 INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3566 double n=INTERP_KERNEL::norm<3>(vals);
3567 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3572 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3573 const double *isAbsPtr=isAbs->getArray()->begin();
3574 for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3575 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3578 else//meshdimension==1
3581 for(int i=0;i<nbOfCells;i++)
3583 int offset=connI[i];
3584 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3585 double n=INTERP_KERNEL::norm<2>(tmp);
3586 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3591 ret->setArray(array);
3593 ret->synchronizeTimeWithSupport();
3598 * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3599 * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3600 * and are normalized.
3601 * <br> \a this can be either
3602 * - a 2D mesh in 2D or 3D space or
3603 * - an 1D mesh in 2D space.
3605 * This method avoids building explicitly a part of \a this mesh to perform the work.
3606 * \param [in] begin - an array of cell ids of interest.
3607 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3608 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3609 * cells and one time. The caller is to delete this field using decrRef() as
3610 * it is no more needed.
3611 * \throw If the nodal connectivity of cells is not defined.
3612 * \throw If the coordinates array is not set.
3613 * \throw If the mesh dimension is not set.
3614 * \throw If the mesh and space dimension is not as specified above.
3615 * \sa buildOrthogonalField()
3617 * \if ENABLE_EXAMPLES
3618 * \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3619 * \ref py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3622 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3624 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3625 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3626 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3627 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3628 std::size_t nbelems=std::distance(begin,end);
3629 int nbComp=getMeshDimension()+1;
3630 array->alloc((int)nbelems,nbComp);
3631 double *vals=array->getPointer();
3632 const int *connI=_nodal_connec_index->getConstPointer();
3633 const int *conn=_nodal_connec->getConstPointer();
3634 const double *coords=_coords->getConstPointer();
3635 if(getMeshDimension()==2)
3637 if(getSpaceDimension()==3)
3639 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3640 const double *locPtr=loc->getConstPointer();
3641 for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3643 int offset=connI[*i];
3644 INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3645 double n=INTERP_KERNEL::norm<3>(vals);
3646 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3651 for(std::size_t i=0;i<nbelems;i++)
3652 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3655 else//meshdimension==1
3658 for(const int *i=begin;i!=end;i++)
3660 int offset=connI[*i];
3661 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3662 double n=INTERP_KERNEL::norm<2>(tmp);
3663 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3668 ret->setArray(array);
3670 ret->synchronizeTimeWithSupport();
3675 * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3676 * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3677 * and are \b not normalized.
3678 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3679 * cells and one time. The caller is to delete this field using decrRef() as
3680 * it is no more needed.
3681 * \throw If the nodal connectivity of cells is not defined.
3682 * \throw If the coordinates array is not set.
3683 * \throw If \a this->getMeshDimension() != 1.
3684 * \throw If \a this mesh includes cells of type other than SEG2.
3686 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3688 if(getMeshDimension()!=1)
3689 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3690 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3691 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3692 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3693 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3694 int nbOfCells=getNumberOfCells();
3695 int spaceDim=getSpaceDimension();
3696 array->alloc(nbOfCells,spaceDim);
3697 double *pt=array->getPointer();
3698 const double *coo=getCoords()->getConstPointer();
3699 std::vector<int> conn;
3701 for(int i=0;i<nbOfCells;i++)
3704 getNodeIdsOfCell(i,conn);
3705 pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3707 ret->setArray(array);
3709 ret->synchronizeTimeWithSupport();
3714 * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3715 * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3716 * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3717 * from. If a result face is shared by two 3D cells, then the face in included twice in
3719 * \param [in] origin - 3 components of a point defining location of the plane.
3720 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3721 * must be greater than 1e-6.
3722 * \param [in] eps - half-thickness of the plane.
3723 * \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3724 * producing correspondent 2D cells. The caller is to delete this array
3725 * using decrRef() as it is no more needed.
3726 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3727 * not share the node coordinates array with \a this mesh. The caller is to
3728 * delete this mesh using decrRef() as it is no more needed.
3729 * \throw If the coordinates array is not set.
3730 * \throw If the nodal connectivity of cells is not defined.
3731 * \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3732 * \throw If magnitude of \a vec is less than 1e-6.
3733 * \throw If the plane does not intersect any 3D cell of \a this mesh.
3734 * \throw If \a this includes quadratic cells.
3736 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3738 checkFullyDefined();
3739 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3740 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3741 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3742 if(candidates->empty())
3743 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3744 std::vector<int> nodes;
3745 DataArrayInt *cellIds1D=0;
3746 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3747 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3748 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3749 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3750 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3751 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3752 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3753 revDesc2=0; revDescIndx2=0;
3754 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3755 revDesc1=0; revDescIndx1=0;
3756 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3757 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3759 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3760 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3762 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3763 std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3764 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3765 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3766 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3767 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3768 connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3769 subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3770 if(cellIds2->empty())
3771 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3772 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3773 ret->setCoords(mDesc1->getCoords());
3774 ret->setConnectivity(conn,connI,true);
3775 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3780 * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3781 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
3782 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3784 * \param [in] origin - 3 components of a point defining location of the plane.
3785 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3786 * must be greater than 1e-6.
3787 * \param [in] eps - half-thickness of the plane.
3788 * \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3789 * producing correspondent segments. The caller is to delete this array
3790 * using decrRef() as it is no more needed.
3791 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3792 * mesh in 3D space. This mesh does not share the node coordinates array with
3793 * \a this mesh. The caller is to delete this mesh using decrRef() as it is
3795 * \throw If the coordinates array is not set.
3796 * \throw If the nodal connectivity of cells is not defined.
3797 * \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3798 * \throw If magnitude of \a vec is less than 1e-6.
3799 * \throw If the plane does not intersect any 2D cell of \a this mesh.
3800 * \throw If \a this includes quadratic cells.
3802 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3804 checkFullyDefined();
3805 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3806 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3807 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3808 if(candidates->empty())
3809 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3810 std::vector<int> nodes;
3811 DataArrayInt *cellIds1D=0;
3812 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3813 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3814 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3815 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3816 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3817 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3818 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3819 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3820 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3822 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3823 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3825 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3826 int ncellsSub=subMesh->getNumberOfCells();
3827 std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3828 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3829 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3830 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3831 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3833 const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3834 const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3835 for(int i=0;i<ncellsSub;i++)
3837 if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3839 if(cut3DSurf[i].first!=-2)
3841 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3842 connI->pushBackSilent(conn->getNumberOfTuples());
3843 cellIds2->pushBackSilent(i);
3847 int cellId3DSurf=cut3DSurf[i].second;
3848 int offset=nodalI[cellId3DSurf]+1;
3849 int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3850 for(int j=0;j<nbOfEdges;j++)
3852 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3853 connI->pushBackSilent(conn->getNumberOfTuples());
3854 cellIds2->pushBackSilent(cellId3DSurf);
3859 if(cellIds2->empty())
3860 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3861 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3862 ret->setCoords(mDesc1->getCoords());
3863 ret->setConnectivity(conn,connI,true);
3864 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3869 * Finds cells whose bounding boxes intersect a given plane.
3870 * \param [in] origin - 3 components of a point defining location of the plane.
3871 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3872 * must be greater than 1e-6.
3873 * \param [in] eps - half-thickness of the plane.
3874 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3875 * cells. The caller is to delete this array using decrRef() as it is no more
3877 * \throw If the coordinates array is not set.
3878 * \throw If the nodal connectivity of cells is not defined.
3879 * \throw If \a this->getSpaceDimension() != 3.
3880 * \throw If magnitude of \a vec is less than 1e-6.
3881 * \sa buildSlice3D()
3883 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3885 checkFullyDefined();
3886 if(getSpaceDimension()!=3)
3887 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3888 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3890 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3892 vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3893 double angle=acos(vec[2]/normm);
3894 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3898 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3899 double normm2(sqrt(vec2[0]*vec2[0]+vec2[1]*vec2[1]+vec2[2]*vec2[2]));
3900 if(normm2/normm>1e-6)
3901 MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3902 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3904 mw->getBoundingBox(bbox);
3905 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3906 cellIds=mw->getCellsInBoundingBox(bbox,eps);
3910 getBoundingBox(bbox);
3911 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3912 cellIds=getCellsInBoundingBox(bbox,eps);
3914 return cellIds.retn();
3918 * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3919 * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3920 * No consideration of coordinate is done by this method.
3921 * 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)
3922 * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3924 bool MEDCouplingUMesh::isContiguous1D() const
3926 if(getMeshDimension()!=1)
3927 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3928 int nbCells=getNumberOfCells();
3930 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3931 const int *connI=_nodal_connec_index->getConstPointer();
3932 const int *conn=_nodal_connec->getConstPointer();
3933 int ref=conn[connI[0]+2];
3934 for(int i=1;i<nbCells;i++)
3936 if(conn[connI[i]+1]!=ref)
3938 ref=conn[connI[i]+2];
3944 * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3945 * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3946 * \param pt reference point of the line
3947 * \param v normalized director vector of the line
3948 * \param eps max precision before throwing an exception
3949 * \param res output of size this->getNumberOfCells
3951 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3953 if(getMeshDimension()!=1)
3954 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3955 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3956 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3957 if(getSpaceDimension()!=3)
3958 throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3959 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3960 const double *fPtr=f->getArray()->getConstPointer();
3962 for(int i=0;i<getNumberOfCells();i++)
3964 const double *tmp1=fPtr+3*i;
3965 tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3966 tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3967 tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3968 double n1=INTERP_KERNEL::norm<3>(tmp);
3969 n1/=INTERP_KERNEL::norm<3>(tmp1);
3971 throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3973 const double *coo=getCoords()->getConstPointer();
3974 for(int i=0;i<getNumberOfNodes();i++)
3976 std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3977 std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3978 res[i]=std::accumulate(tmp,tmp+3,0.);
3983 * 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.
3984 * \a this is expected to be a mesh so that its space dimension is equal to its
3985 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3986 * 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).
3988 * 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
3989 * 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).
3990 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3992 * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3993 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3995 * \param [in] ptBg the start pointer (included) of the coordinates of the point
3996 * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3997 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3998 * \return the positive value of the distance.
3999 * \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
4001 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
4003 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
4005 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4006 if(meshDim!=spaceDim-1)
4007 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
4008 if(meshDim!=2 && meshDim!=1)
4009 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4010 checkFullyDefined();
4011 if((int)std::distance(ptBg,ptEnd)!=spaceDim)
4012 { 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()); }
4013 DataArrayInt *ret1=0;
4014 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
4015 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
4016 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
4017 cellId=*ret1Safe->begin();
4018 return *ret0->begin();
4022 * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
4023 * to \a this and the first \a cellId in \a this corresponding to the returned distance.
4024 * 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
4025 * 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).
4026 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4028 * \a this is expected to be a mesh so that its space dimension is equal to its
4029 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4030 * 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).
4032 * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
4033 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4035 * \param [in] pts the list of points in which each tuple represents a point
4036 * \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.
4037 * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
4038 * \throw if number of components of \a pts is not equal to the space dimension.
4039 * \throw if mesh dimension of \a this is not equal to space dimension - 1.
4040 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
4042 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
4045 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
4046 pts->checkAllocated();
4047 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4048 if(meshDim!=spaceDim-1)
4049 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
4050 if(meshDim!=2 && meshDim!=1)
4051 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
4052 if(pts->getNumberOfComponents()!=spaceDim)
4054 std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
4055 throw INTERP_KERNEL::Exception(oss.str().c_str());
4057 checkFullyDefined();
4058 int nbCells=getNumberOfCells();
4060 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4061 int nbOfPts=pts->getNumberOfTuples();
4062 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4063 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4064 const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4065 double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4066 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4067 const double *bbox(bboxArr->begin());
4072 BBTreeDst<3> myTree(bbox,0,0,nbCells);
4073 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4075 double x=std::numeric_limits<double>::max();
4076 std::vector<int> elems;
4077 myTree.getMinDistanceOfMax(ptsPtr,x);
4078 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4079 DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4085 BBTreeDst<2> myTree(bbox,0,0,nbCells);
4086 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4088 double x=std::numeric_limits<double>::max();
4089 std::vector<int> elems;
4090 myTree.getMinDistanceOfMax(ptsPtr,x);
4091 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4092 DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4097 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4099 cellIds=ret1.retn();
4104 * \param [in] pt the start pointer (included) of the coordinates of the point
4105 * \param [in] cellIdsBg the start pointer (included) of cellIds
4106 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4107 * \param [in] nc nodal connectivity
4108 * \param [in] ncI nodal connectivity index
4109 * \param [in,out] ret0 the min distance between \a this and the external input point
4110 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4111 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4113 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)
4116 ret0=std::numeric_limits<double>::max();
4117 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4119 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4121 case INTERP_KERNEL::NORM_TRI3:
4123 double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4125 { ret0=tmp; cellId=*zeCell; }
4128 case INTERP_KERNEL::NORM_QUAD4:
4129 case INTERP_KERNEL::NORM_POLYGON:
4131 double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4133 { ret0=tmp; cellId=*zeCell; }
4137 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4143 * \param [in] pt the start pointer (included) of the coordinates of the point
4144 * \param [in] cellIdsBg the start pointer (included) of cellIds
4145 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4146 * \param [in] nc nodal connectivity
4147 * \param [in] ncI nodal connectivity index
4148 * \param [in,out] ret0 the min distance between \a this and the external input point
4149 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4150 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4152 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)
4155 ret0=std::numeric_limits<double>::max();
4156 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4158 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4160 case INTERP_KERNEL::NORM_SEG2:
4162 std::size_t uselessEntry=0;
4163 double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4166 { ret0=tmp; cellId=*zeCell; }
4170 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4176 * Finds cells in contact with a ball (i.e. a point with precision).
4177 * For speed reasons, the INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6 and INTERP_KERNEL::NORM_QUAD8 cells are considered as convex cells to detect if a point is IN or OUT.
4178 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4180 * \warning This method is suitable if the caller intends to evaluate only one
4181 * point, for more points getCellsContainingPoints() is recommended as it is
4183 * \param [in] pos - array of coordinates of the ball central point.
4184 * \param [in] eps - ball radius.
4185 * \return int - a smallest id of cells being in contact with the ball, -1 in case
4186 * if there are no such cells.
4187 * \throw If the coordinates array is not set.
4188 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4190 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4192 std::vector<int> elts;
4193 getCellsContainingPoint(pos,eps,elts);
4196 return elts.front();
4200 * Finds cells in contact with a ball (i.e. a point with precision).
4201 * For speed reasons, the INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6 and INTERP_KERNEL::NORM_QUAD8 cells are considered as convex cells to detect if a point is IN or OUT.
4202 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4203 * \warning This method is suitable if the caller intends to evaluate only one
4204 * point, for more points getCellsContainingPoints() is recommended as it is
4206 * \param [in] pos - array of coordinates of the ball central point.
4207 * \param [in] eps - ball radius.
4208 * \param [out] elts - vector returning ids of the found cells. It is cleared
4209 * before inserting ids.
4210 * \throw If the coordinates array is not set.
4211 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4213 * \if ENABLE_EXAMPLES
4214 * \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4215 * \ref py_mcumesh_getCellsContainingPoint "Here is a Python example".
4218 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4220 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4221 getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4222 elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4227 namespace ParaMEDMEM
4229 template<const int SPACEDIMM>
4233 static const int MY_SPACEDIM=SPACEDIMM;
4234 static const int MY_MESHDIM=8;
4235 typedef int MyConnType;
4236 static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4238 // useless, but for windows compilation ...
4239 const double* getCoordinatesPtr() const { return 0; }
4240 const int* getConnectivityPtr() const { return 0; }
4241 const int* getConnectivityIndexPtr() const { return 0; }
4242 INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4249 * Warning the nodes in \a m should be decrRefed ! To avoid that Node * pointer be replaced by another instance.
4251 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m)
4253 INTERP_KERNEL::Edge *ret(0);
4254 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> n0(new INTERP_KERNEL::Node(coords2D[2*bg[0]],coords2D[2*bg[0]+1])),n1(new INTERP_KERNEL::Node(coords2D[2*bg[1]],coords2D[2*bg[1]+1]));
4255 m[n0]=bg[0]; m[n1]=bg[1];
4258 case INTERP_KERNEL::NORM_SEG2:
4260 ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4263 case INTERP_KERNEL::NORM_SEG3:
4265 INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4266 INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4267 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4268 // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4269 bool colinearity(inters.areColinears());
4270 delete e1; delete e2;
4272 { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4274 { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4278 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4283 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4285 INTERP_KERNEL::Edge *ret=0;
4288 case INTERP_KERNEL::NORM_SEG2:
4290 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4293 case INTERP_KERNEL::NORM_SEG3:
4295 INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4296 INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4297 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4298 // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4299 bool colinearity=inters.areColinears();
4300 delete e1; delete e2;
4302 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4304 ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4305 mapp2[bg[2]].second=false;
4309 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4315 * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4316 * the global mesh 'mDesc'.
4317 * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4318 * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4320 INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4321 std::map<INTERP_KERNEL::Node *,int>& mapp)
4324 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.
4325 const double *coo=mDesc->getCoords()->getConstPointer();
4326 const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4327 const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4329 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4330 s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4331 for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4333 INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4334 mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4336 INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4337 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4339 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4340 ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4342 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4344 if((*it2).second.second)
4345 mapp[(*it2).second.first]=(*it2).first;
4346 ((*it2).second.first)->decrRef();
4351 INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4355 int locId=nodeId-offset2;
4356 return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4360 int locId=nodeId-offset1;
4361 return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4363 return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4367 * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4369 void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4370 const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4371 /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4373 for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4375 int eltId1=abs(*desc1)-1;
4376 for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4378 std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4379 if(it==mappRev.end())
4381 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4392 template<int SPACEDIM>
4393 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4394 double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4396 elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4397 int *eltsIndexPtr(eltsIndex->getPointer());
4398 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4399 const double *bbox(bboxArr->begin());
4400 int nbOfCells=getNumberOfCells();
4401 const int *conn=_nodal_connec->getConstPointer();
4402 const int *connI=_nodal_connec_index->getConstPointer();
4403 double bb[2*SPACEDIM];
4404 BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4405 for(int i=0;i<nbOfPoints;i++)
4407 eltsIndexPtr[i+1]=eltsIndexPtr[i];
4408 for(int j=0;j<SPACEDIM;j++)
4410 bb[2*j]=pos[SPACEDIM*i+j];
4411 bb[2*j+1]=pos[SPACEDIM*i+j];
4413 std::vector<int> candidates;
4414 myTree.getIntersectingElems(bb,candidates);
4415 for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4417 int sz(connI[(*iter)+1]-connI[*iter]-1);
4418 INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4420 if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4421 status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4425 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4426 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4427 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4428 std::vector<INTERP_KERNEL::Node *> nodes(sz);
4429 INTERP_KERNEL::QuadraticPolygon *pol(0);
4430 for(int j=0;j<sz;j++)
4432 int nodeId(conn[connI[*iter]+1+j]);
4433 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4435 if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4436 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4438 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4439 INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4440 double a(0.),b(0.),c(0.);
4441 a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4442 status=pol->isInOrOut2(n);
4443 delete pol; n->decrRef();
4447 eltsIndexPtr[i+1]++;
4448 elts->pushBackSilent(*iter);
4454 * Finds cells in contact with several balls (i.e. points with precision).
4455 * This method is an extension of getCellContainingPoint() and
4456 * getCellsContainingPoint() for the case of multiple points.
4457 * For speed reasons, the INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6 and INTERP_KERNEL::NORM_QUAD8 cells are considered as convex cells to detect if a point is IN or OUT.
4458 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4459 * \param [in] pos - an array of coordinates of points in full interlace mode :
4460 * X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4461 * this->getSpaceDimension() * \a nbOfPoints
4462 * \param [in] nbOfPoints - number of points to locate within \a this mesh.
4463 * \param [in] eps - radius of balls (i.e. the precision).
4464 * \param [out] elts - vector returning ids of found cells.
4465 * \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4466 * dividing cell ids in \a elts into groups each referring to one
4467 * point. Its every element (except the last one) is an index pointing to the
4468 * first id of a group of cells. For example cells in contact with the *i*-th
4469 * point are described by following range of indices:
4470 * [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4471 * \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4472 * Number of cells in contact with the *i*-th point is
4473 * \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4474 * \throw If the coordinates array is not set.
4475 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4477 * \if ENABLE_EXAMPLES
4478 * \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4479 * \ref py_mcumesh_getCellsContainingPoints "Here is a Python example".
4482 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4483 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4485 int spaceDim=getSpaceDimension();
4486 int mDim=getMeshDimension();
4491 const double *coords=_coords->getConstPointer();
4492 getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4499 throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4501 else if(spaceDim==2)
4505 const double *coords=_coords->getConstPointer();
4506 getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4509 throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4511 else if(spaceDim==1)
4515 const double *coords=_coords->getConstPointer();
4516 getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4519 throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4522 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4526 * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4527 * least two its edges intersect each other anywhere except their extremities. An
4528 * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4529 * \param [in,out] cells - a vector returning ids of the found cells. It is not
4530 * cleared before filling in.
4531 * \param [in] eps - precision.
4532 * \throw If \a this->getMeshDimension() != 2.
4533 * \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4535 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4537 const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4538 if(getMeshDimension()!=2)
4539 throw INTERP_KERNEL::Exception(msg);
4540 int spaceDim=getSpaceDimension();
4541 if(spaceDim!=2 && spaceDim!=3)
4542 throw INTERP_KERNEL::Exception(msg);
4543 const int *conn=_nodal_connec->getConstPointer();
4544 const int *connI=_nodal_connec_index->getConstPointer();
4545 int nbOfCells=getNumberOfCells();
4546 std::vector<double> cell2DinS2;
4547 for(int i=0;i<nbOfCells;i++)
4549 int offset=connI[i];
4550 int nbOfNodesForCell=connI[i+1]-offset-1;
4551 if(nbOfNodesForCell<=3)
4553 bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4554 project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4555 if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4562 * This method is typically requested to unbutterfly 2D linear cells in \b this.
4564 * 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.
4565 * 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.
4567 * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4568 * This convex envelop is computed using Jarvis march algorithm.
4569 * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4570 * 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)
4571 * 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.
4573 * \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.
4574 * \sa MEDCouplingUMesh::colinearize2D
4576 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4578 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4579 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D works only for meshDim=2 and spaceDim=2 !");
4580 checkFullyDefined();
4581 const double *coords=getCoords()->getConstPointer();
4582 int nbOfCells=getNumberOfCells();
4583 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4584 nodalConnecIndexOut->alloc(nbOfCells+1,1);
4585 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4586 int *workIndexOut=nodalConnecIndexOut->getPointer();
4588 const int *nodalConnecIn=_nodal_connec->getConstPointer();
4589 const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4590 std::set<INTERP_KERNEL::NormalizedCellType> types;
4591 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4592 isChanged->alloc(0,1);
4593 for(int i=0;i<nbOfCells;i++,workIndexOut++)
4595 int pos=nodalConnecOut->getNumberOfTuples();
4596 if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4597 isChanged->pushBackSilent(i);
4598 types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4599 workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4601 if(isChanged->empty())
4603 setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4605 return isChanged.retn();
4609 * This method is \b NOT const because it can modify \a this.
4610 * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4611 * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4612 * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4613 * \b 1 for translation and rotation around point of 'mesh1D'.
4614 * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.
4616 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4618 checkFullyDefined();
4619 mesh1D->checkFullyDefined();
4620 if(!mesh1D->isContiguous1D())
4621 throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4622 if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4623 throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4624 if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4625 throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4626 if(mesh1D->getMeshDimension()!=1)
4627 throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4629 if(isPresenceOfQuadratic())
4631 if(mesh1D->isFullyQuadratic())
4634 throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4637 int oldNbOfNodes=getNumberOfNodes();
4638 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4643 newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4648 newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4652 throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4654 setCoords(newCoords);
4655 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4661 * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4662 * If it is not the case an exception will be thrown.
4663 * This method is non const because the coordinate of \a this can be appended with some new points issued from
4664 * intersection of plane defined by ('origin','vec').
4665 * This method has one in/out parameter : 'cut3DCurve'.
4666 * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4667 * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4668 * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4669 * This method will throw an exception if \a this contains a non linear segment.
4671 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4673 checkFullyDefined();
4674 if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4675 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4676 int ncells=getNumberOfCells();
4677 int nnodes=getNumberOfNodes();
4678 double vec2[3],vec3[3],vec4[3];
4679 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4681 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4682 vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4683 const int *conn=_nodal_connec->getConstPointer();
4684 const int *connI=_nodal_connec_index->getConstPointer();
4685 const double *coo=_coords->getConstPointer();
4686 std::vector<double> addCoo;
4687 for(int i=0;i<ncells;i++)
4689 if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4691 if(cut3DCurve[i]==-2)
4693 int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4694 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];
4695 double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4696 double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4697 if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4699 const double *st2=coo+3*st;
4700 vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4701 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]));
4702 if(pos>eps && pos<1-eps)
4704 int nNode=((int)addCoo.size())/3;
4705 vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4706 addCoo.insert(addCoo.end(),vec4,vec4+3);
4707 cut3DCurve[i]=nnodes+nNode;
4713 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4717 int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4718 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4719 coo2->alloc(newNbOfNodes,3);
4720 double *tmp=coo2->getPointer();
4721 tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4722 std::copy(addCoo.begin(),addCoo.end(),tmp);
4723 DataArrayDouble::SetArrayIn(coo2,_coords);
4728 * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4729 * \param mesh1D is the input 1D mesh used for translation computation.
4730 * \return newCoords new coords filled by this method.
4732 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4734 int oldNbOfNodes=getNumberOfNodes();
4735 int nbOf1DCells=mesh1D->getNumberOfCells();
4736 int spaceDim=getSpaceDimension();
4737 DataArrayDouble *ret=DataArrayDouble::New();
4738 std::vector<bool> isQuads;
4739 int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4740 ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4741 double *retPtr=ret->getPointer();
4742 const double *coords=getCoords()->getConstPointer();
4743 double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4745 std::vector<double> c;
4749 for(int i=0;i<nbOf1DCells;i++)
4752 mesh1D->getNodeIdsOfCell(i,v);
4754 mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4755 mesh1D->getCoordinatesOfNode(v[0],c);
4756 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4757 for(int j=0;j<oldNbOfNodes;j++)
4758 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4762 mesh1D->getCoordinatesOfNode(v[1],c);
4763 mesh1D->getCoordinatesOfNode(v[0],c);
4764 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4765 for(int j=0;j<oldNbOfNodes;j++)
4766 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4769 ret->copyStringInfoFrom(*getCoords());
4774 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4775 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4776 * \return newCoords new coords filled by this method.
4778 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4780 if(mesh1D->getSpaceDimension()==2)
4781 return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4782 if(mesh1D->getSpaceDimension()==3)
4783 return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4784 throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4788 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4789 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4790 * \return newCoords new coords filled by this method.
4792 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4795 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4796 int oldNbOfNodes=getNumberOfNodes();
4797 int nbOf1DCells=mesh1D->getNumberOfCells();
4799 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4800 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4801 int nbOfLevsInVec=nbOf1DCells+1;
4802 ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4803 double *retPtr=ret->getPointer();
4804 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4805 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4806 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4807 tmp->setCoords(tmp2);
4808 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4809 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4810 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4811 for(int i=1;i<nbOfLevsInVec;i++)
4813 const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4814 const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4815 const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4816 const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4817 tmp->translate(vec);
4818 double tmp3[2],radius,alpha,alpha0;
4819 const double *p0=i+1<nbOfLevsInVec?begin:third;
4820 const double *p1=i+1<nbOfLevsInVec?end:begin;
4821 const double *p2=i+1<nbOfLevsInVec?third:end;
4822 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4823 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]);
4824 double angle=acos(cosangle/(radius*radius));
4825 tmp->rotate(end,0,angle);
4826 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4832 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4833 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4834 * \return newCoords new coords filled by this method.
4836 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4839 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4840 int oldNbOfNodes=getNumberOfNodes();
4841 int nbOf1DCells=mesh1D->getNumberOfCells();
4843 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4844 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4845 int nbOfLevsInVec=nbOf1DCells+1;
4846 ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4847 double *retPtr=ret->getPointer();
4848 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4849 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4850 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4851 tmp->setCoords(tmp2);
4852 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4853 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4854 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4855 for(int i=1;i<nbOfLevsInVec;i++)
4857 const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4858 const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4859 const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4860 const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4861 tmp->translate(vec);
4862 double tmp3[2],radius,alpha,alpha0;
4863 const double *p0=i+1<nbOfLevsInVec?begin:third;
4864 const double *p1=i+1<nbOfLevsInVec?end:begin;
4865 const double *p2=i+1<nbOfLevsInVec?third:end;
4866 double vecPlane[3]={
4867 (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4868 (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4869 (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4871 double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4874 vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4875 double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4876 double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4878 double c2=cos(asin(s2));
4880 {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4881 {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4882 {-vec2[1]*s2, vec2[0]*s2, c2}
4884 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]};
4885 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]};
4886 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]};
4887 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4888 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]);
4889 double angle=acos(cosangle/(radius*radius));
4890 tmp->rotate(end,vecPlane,angle);
4892 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4898 * This method is private because not easy to use for end user. This method is const contrary to
4899 * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4900 * the coords sorted slice by slice.
4901 * \param isQuad specifies presence of quadratic cells.
4903 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4905 int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4906 int nbOf2DCells=getNumberOfCells();
4907 int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4908 MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4909 const int *conn=_nodal_connec->getConstPointer();
4910 const int *connI=_nodal_connec_index->getConstPointer();
4911 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4912 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4913 newConnI->alloc(nbOf3DCells+1,1);
4914 int *newConnIPtr=newConnI->getPointer();
4916 std::vector<int> newc;
4917 for(int j=0;j<nbOf2DCells;j++)
4919 AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4920 *newConnIPtr++=(int)newc.size();
4922 newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4923 int *newConnPtr=newConn->getPointer();
4924 int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4925 newConnIPtr=newConnI->getPointer();
4926 for(int iz=0;iz<nbOf1DCells;iz++)
4929 std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4930 for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4932 int icell=(int)(iter-newc.begin());
4933 if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4936 *newConnPtr=(*iter)+iz*deltaPerLev;
4941 *newConnPtr=(*iter);
4944 ret->setConnectivity(newConn,newConnI,true);
4945 ret->setCoords(getCoords());
4950 * Checks if \a this mesh is constituted by only quadratic cells.
4951 * \return bool - \c true if there are only quadratic cells in \a this mesh.
4952 * \throw If the coordinates array is not set.
4953 * \throw If the nodal connectivity of cells is not defined.
4955 bool MEDCouplingUMesh::isFullyQuadratic() const
4957 checkFullyDefined();
4959 int nbOfCells=getNumberOfCells();
4960 for(int i=0;i<nbOfCells && ret;i++)
4962 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4963 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4964 ret=cm.isQuadratic();
4970 * Checks if \a this mesh includes any quadratic cell.
4971 * \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4972 * \throw If the coordinates array is not set.
4973 * \throw If the nodal connectivity of cells is not defined.
4975 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4977 checkFullyDefined();
4979 int nbOfCells=getNumberOfCells();
4980 for(int i=0;i<nbOfCells && !ret;i++)
4982 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4983 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4984 ret=cm.isQuadratic();
4990 * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4991 * this mesh, it remains unchanged.
4992 * \throw If the coordinates array is not set.
4993 * \throw If the nodal connectivity of cells is not defined.
4995 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4997 checkFullyDefined();
4998 int nbOfCells=getNumberOfCells();
5000 const int *iciptr=_nodal_connec_index->getConstPointer();
5001 for(int i=0;i<nbOfCells;i++)
5003 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5004 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5005 if(cm.isQuadratic())
5007 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5008 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5009 if(!cml.isDynamic())
5010 delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
5012 delta+=(iciptr[i+1]-iciptr[i]-1)/2;
5017 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5018 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5019 const int *icptr=_nodal_connec->getConstPointer();
5020 newConn->alloc(getMeshLength()-delta,1);
5021 newConnI->alloc(nbOfCells+1,1);
5022 int *ocptr=newConn->getPointer();
5023 int *ociptr=newConnI->getPointer();
5026 for(int i=0;i<nbOfCells;i++,ociptr++)
5028 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
5029 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5030 if(!cm.isQuadratic())
5032 _types.insert(type);
5033 ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5034 ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5038 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5039 _types.insert(typel);
5040 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5041 int newNbOfNodes=cml.getNumberOfNodes();
5043 newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
5044 *ocptr++=(int)typel;
5045 ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5046 ociptr[1]=ociptr[0]+newNbOfNodes+1;
5049 setConnectivity(newConn,newConnI,false);
5053 * This method converts all linear cell in \a this to quadratic one.
5054 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5055 * 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)
5056 * 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.
5057 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5058 * end of the existing coordinates.
5060 * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5061 * corresponding quadratic cells. 1 is those creating the 'most' complex.
5062 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5064 * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5066 * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5068 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5070 DataArrayInt *conn=0,*connI=0;
5071 DataArrayDouble *coords=0;
5072 std::set<INTERP_KERNEL::NormalizedCellType> types;
5073 checkFullyDefined();
5074 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5075 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5076 int meshDim=getMeshDimension();
5077 switch(conversionType)
5083 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5084 connSafe=conn; connISafe=connI; coordsSafe=coords;
5087 ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5088 connSafe=conn; connISafe=connI; coordsSafe=coords;
5091 ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5092 connSafe=conn; connISafe=connI; coordsSafe=coords;
5095 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5103 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5104 connSafe=conn; connISafe=connI; coordsSafe=coords;
5107 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5108 connSafe=conn; connISafe=connI; coordsSafe=coords;
5111 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5112 connSafe=conn; connISafe=connI; coordsSafe=coords;
5115 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5120 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5122 setConnectivity(connSafe,connISafe,false);
5124 setCoords(coordsSafe);
5130 * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
5131 * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
5132 * The nodes to be added in those 2D cells are defined by the pair of \a nodeIdsToAdd and \a nodeIdsIndexToAdd.
5133 * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
5134 * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
5135 * This method can be seen as the opposite method of colinearize2D.
5136 * This method can be lead to create some new nodes if quadratic polygon cells have to be split. In this case the added nodes will be put at the end
5137 * to avoid to modify the numbering of existing nodes.
5139 * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
5140 * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
5141 * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
5142 * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
5143 * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
5144 * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
5145 * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
5147 * \sa buildDescendingConnectivity2
5149 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
5150 const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
5152 if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
5153 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
5154 nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
5155 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
5156 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
5157 if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
5158 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
5159 //DataArrayInt *out0(0),*outi0(0);
5160 //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
5161 //MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s(out0),outi0s(outi0);
5162 //out0s=out0s->buildUnique(); out0s->sort(true);
5167 * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5168 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5169 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5171 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5173 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5174 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5175 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5176 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5177 int nbOfCells=getNumberOfCells();
5178 int nbOfNodes=getNumberOfNodes();
5179 const int *cPtr=_nodal_connec->getConstPointer();
5180 const int *icPtr=_nodal_connec_index->getConstPointer();
5181 int lastVal=0,offset=nbOfNodes;
5182 for(int i=0;i<nbOfCells;i++,icPtr++)
5184 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5185 if(type==INTERP_KERNEL::NORM_SEG2)
5187 types.insert(INTERP_KERNEL::NORM_SEG3);
5188 newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5189 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5190 newConn->pushBackSilent(offset++);
5192 newConnI->pushBackSilent(lastVal);
5193 ret->pushBackSilent(i);
5198 lastVal+=(icPtr[1]-icPtr[0]);
5199 newConnI->pushBackSilent(lastVal);
5200 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5203 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5204 coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5208 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
5210 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5211 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5212 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5214 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5215 DataArrayInt *conn1D=0,*conn1DI=0;
5216 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5217 DataArrayDouble *coordsTmp=0;
5218 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5219 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5220 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5221 const int *c1DPtr=conn1D->begin();
5222 const int *c1DIPtr=conn1DI->begin();
5223 int nbOfCells=getNumberOfCells();
5224 const int *cPtr=_nodal_connec->getConstPointer();
5225 const int *icPtr=_nodal_connec_index->getConstPointer();
5227 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5229 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5230 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5231 if(!cm.isQuadratic())
5233 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5234 types.insert(typ2); newConn->pushBackSilent(typ2);
5235 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5236 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5237 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5238 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5239 newConnI->pushBackSilent(lastVal);
5240 ret->pushBackSilent(i);
5245 lastVal+=(icPtr[1]-icPtr[0]);
5246 newConnI->pushBackSilent(lastVal);
5247 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5250 conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5255 * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5256 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5257 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5259 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5261 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5262 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5263 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5266 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5268 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5269 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5271 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5272 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5273 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5275 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5276 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5277 DataArrayInt *conn1D=0,*conn1DI=0;
5278 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5279 DataArrayDouble *coordsTmp=0;
5280 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5281 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5282 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5283 const int *c1DPtr=conn1D->begin();
5284 const int *c1DIPtr=conn1DI->begin();
5285 int nbOfCells=getNumberOfCells();
5286 const int *cPtr=_nodal_connec->getConstPointer();
5287 const int *icPtr=_nodal_connec_index->getConstPointer();
5288 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5289 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5291 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5292 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5293 if(!cm.isQuadratic())
5295 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5296 types.insert(typ2); newConn->pushBackSilent(typ2);
5297 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5298 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5299 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5300 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5301 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5302 newConnI->pushBackSilent(lastVal);
5303 ret->pushBackSilent(i);
5308 lastVal+=(icPtr[1]-icPtr[0]);
5309 newConnI->pushBackSilent(lastVal);
5310 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5313 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5314 coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5319 * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5320 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5321 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5323 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5325 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5326 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5327 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5330 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5332 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5333 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5334 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5335 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5337 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5338 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5339 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5341 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5342 const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5343 DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5344 std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5345 DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5346 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5347 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5348 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5349 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5350 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5351 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5352 const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5353 int nbOfCells=getNumberOfCells();
5354 const int *cPtr=_nodal_connec->getConstPointer();
5355 const int *icPtr=_nodal_connec_index->getConstPointer();
5356 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5357 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5359 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5360 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5361 if(!cm.isQuadratic())
5363 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5364 if(typ2==INTERP_KERNEL::NORM_ERROR)
5366 std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5367 throw INTERP_KERNEL::Exception(oss.str().c_str());
5369 types.insert(typ2); newConn->pushBackSilent(typ2);
5370 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5371 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5372 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5373 for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5375 int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5376 int tmpPos=newConn->getNumberOfTuples();
5377 newConn->pushBackSilent(nodeId2);
5378 ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5380 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5381 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5382 newConnI->pushBackSilent(lastVal);
5383 ret->pushBackSilent(i);
5388 lastVal+=(icPtr[1]-icPtr[0]);
5389 newConnI->pushBackSilent(lastVal);
5390 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5393 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5394 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5395 coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5396 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5397 std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5398 int *c=newConn->getPointer();
5399 const int *cI(newConnI->begin());
5400 for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5401 c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5402 offset=coordsTmp2Safe->getNumberOfTuples();
5403 for(const int *elt=ret->begin();elt!=ret->end();elt++)
5404 c[cI[(*elt)+1]-1]+=offset;
5405 coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5410 * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5411 * so that the number of cells remains the same. Quadratic faces are converted to
5412 * polygons. This method works only for 2D meshes in
5413 * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5414 * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5415 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5416 * \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5417 * a polylinized edge constituting the input polygon.
5418 * \throw If the coordinates array is not set.
5419 * \throw If the nodal connectivity of cells is not defined.
5420 * \throw If \a this->getMeshDimension() != 2.
5421 * \throw If \a this->getSpaceDimension() != 2.
5423 void MEDCouplingUMesh::tessellate2D(double eps)
5425 checkFullyDefined();
5426 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
5427 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5428 double epsa=fabs(eps);
5429 if(epsa<std::numeric_limits<double>::min())
5430 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 !");
5431 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5432 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5433 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5434 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5435 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5436 revDesc1=0; revDescIndx1=0;
5437 mDesc->tessellate2DCurve(eps);
5438 subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5439 setCoords(mDesc->getCoords());
5443 * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5444 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5445 * \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5446 * a sub-divided edge.
5447 * \throw If the coordinates array is not set.
5448 * \throw If the nodal connectivity of cells is not defined.
5449 * \throw If \a this->getMeshDimension() != 1.
5450 * \throw If \a this->getSpaceDimension() != 2.
5452 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5454 checkFullyDefined();
5455 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5456 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5457 double epsa=fabs(eps);
5458 if(epsa<std::numeric_limits<double>::min())
5459 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 !");
5460 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5461 int nbCells=getNumberOfCells();
5462 int nbNodes=getNumberOfNodes();
5463 const int *conn=_nodal_connec->getConstPointer();
5464 const int *connI=_nodal_connec_index->getConstPointer();
5465 const double *coords=_coords->getConstPointer();
5466 std::vector<double> addCoo;
5467 std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5468 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5469 newConnI->alloc(nbCells+1,1);
5470 int *newConnIPtr=newConnI->getPointer();
5473 INTERP_KERNEL::Node *tmp2[3];
5474 std::set<INTERP_KERNEL::NormalizedCellType> types;
5475 for(int i=0;i<nbCells;i++,newConnIPtr++)
5477 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5478 if(cm.isQuadratic())
5479 {//assert(connI[i+1]-connI[i]-1==3)
5480 tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5481 tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5482 tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5483 tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5484 INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5487 eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5488 types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5490 newConnIPtr[1]=(int)newConn.size();
5494 types.insert(INTERP_KERNEL::NORM_SEG2);
5495 newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5496 newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5497 newConnIPtr[1]=newConnIPtr[0]+3;
5502 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5503 newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5504 newConnIPtr[1]=newConnIPtr[0]+3;
5507 if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5510 DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5511 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5512 newConnArr->alloc((int)newConn.size(),1);
5513 std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5514 DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5515 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5516 newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5517 double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5518 std::copy(addCoo.begin(),addCoo.end(),work);
5519 DataArrayDouble::SetArrayIn(newCoords,_coords);
5524 * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5525 * In addition, returns an array mapping new cells to old ones. <br>
5526 * This method typically increases the number of cells in \a this mesh
5527 * but the number of nodes remains \b unchanged.
5528 * That's why the 3D splitting policies
5529 * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5530 * \param [in] policy - specifies a pattern used for splitting.
5531 * The semantic of \a policy is:
5532 * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5533 * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5534 * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8 into 5 TETRA4 (for 3D mesh only).
5535 * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8 into 6 TETRA4 (for 3D mesh only).
5536 * \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5537 * an id of old cell producing it. The caller is to delete this array using
5538 * decrRef() as it is no more needed.
5539 * \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5540 * \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5541 * and \a this->getMeshDimension() != 3.
5542 * \throw If \a policy is not one of the four discussed above.
5543 * \throw If the nodal connectivity of cells is not defined.
5544 * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5546 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5551 return simplexizePol0();
5553 return simplexizePol1();
5554 case (int) INTERP_KERNEL::PLANAR_FACE_5:
5555 return simplexizePlanarFace5();
5556 case (int) INTERP_KERNEL::PLANAR_FACE_6:
5557 return simplexizePlanarFace6();
5559 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)");
5564 * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5565 * - 1D: INTERP_KERNEL::NORM_SEG2
5566 * - 2D: INTERP_KERNEL::NORM_TRI3
5567 * - 3D: INTERP_KERNEL::NORM_TETRA4.
5569 * This method is useful for users that need to use P1 field services as
5570 * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5571 * All these methods need mesh support containing only simplex cells.
5572 * \return bool - \c true if there are only simplex cells in \a this mesh.
5573 * \throw If the coordinates array is not set.
5574 * \throw If the nodal connectivity of cells is not defined.
5575 * \throw If \a this->getMeshDimension() < 1.
5577 bool MEDCouplingUMesh::areOnlySimplexCells() const
5579 checkFullyDefined();
5580 int mdim=getMeshDimension();
5581 if(mdim<1 || mdim>3)
5582 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5583 int nbCells=getNumberOfCells();
5584 const int *conn=_nodal_connec->getConstPointer();
5585 const int *connI=_nodal_connec_index->getConstPointer();
5586 for(int i=0;i<nbCells;i++)
5588 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5596 * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5598 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5600 checkConnectivityFullyDefined();
5601 if(getMeshDimension()!=2)
5602 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5603 int nbOfCells=getNumberOfCells();
5604 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5605 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5606 ret->alloc(nbOfCells+nbOfCutCells,1);
5607 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5608 int *retPt=ret->getPointer();
5609 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5610 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5611 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5612 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5613 int *pt=newConn->getPointer();
5614 int *ptI=newConnI->getPointer();
5616 const int *oldc=_nodal_connec->getConstPointer();
5617 const int *ci=_nodal_connec_index->getConstPointer();
5618 for(int i=0;i<nbOfCells;i++,ci++)
5620 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5622 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5623 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5624 pt=std::copy(tmp,tmp+8,pt);
5633 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5634 ptI[1]=ptI[0]+ci[1]-ci[0];
5639 _nodal_connec->decrRef();
5640 _nodal_connec=newConn.retn();
5641 _nodal_connec_index->decrRef();
5642 _nodal_connec_index=newConnI.retn();
5649 * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5651 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5653 checkConnectivityFullyDefined();
5654 if(getMeshDimension()!=2)
5655 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5656 int nbOfCells=getNumberOfCells();
5657 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5658 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5659 ret->alloc(nbOfCells+nbOfCutCells,1);
5660 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5661 int *retPt=ret->getPointer();
5662 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5663 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5664 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5665 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5666 int *pt=newConn->getPointer();
5667 int *ptI=newConnI->getPointer();
5669 const int *oldc=_nodal_connec->getConstPointer();
5670 const int *ci=_nodal_connec_index->getConstPointer();
5671 for(int i=0;i<nbOfCells;i++,ci++)
5673 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5675 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5676 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5677 pt=std::copy(tmp,tmp+8,pt);
5686 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5687 ptI[1]=ptI[0]+ci[1]-ci[0];
5692 _nodal_connec->decrRef();
5693 _nodal_connec=newConn.retn();
5694 _nodal_connec_index->decrRef();
5695 _nodal_connec_index=newConnI.retn();
5702 * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5704 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5706 checkConnectivityFullyDefined();
5707 if(getMeshDimension()!=3)
5708 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5709 int nbOfCells=getNumberOfCells();
5710 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5711 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5712 ret->alloc(nbOfCells+4*nbOfCutCells,1);
5713 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5714 int *retPt=ret->getPointer();
5715 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5716 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5717 newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5718 newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5719 int *pt=newConn->getPointer();
5720 int *ptI=newConnI->getPointer();
5722 const int *oldc=_nodal_connec->getConstPointer();
5723 const int *ci=_nodal_connec_index->getConstPointer();
5724 for(int i=0;i<nbOfCells;i++,ci++)
5726 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5728 for(int j=0;j<5;j++,pt+=5,ptI++)
5730 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5731 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];
5738 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5739 ptI[1]=ptI[0]+ci[1]-ci[0];
5744 _nodal_connec->decrRef();
5745 _nodal_connec=newConn.retn();
5746 _nodal_connec_index->decrRef();
5747 _nodal_connec_index=newConnI.retn();
5754 * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5756 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5758 checkConnectivityFullyDefined();
5759 if(getMeshDimension()!=3)
5760 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5761 int nbOfCells=getNumberOfCells();
5762 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5763 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5764 ret->alloc(nbOfCells+5*nbOfCutCells,1);
5765 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5766 int *retPt=ret->getPointer();
5767 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5768 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5769 newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5770 newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5771 int *pt=newConn->getPointer();
5772 int *ptI=newConnI->getPointer();
5774 const int *oldc=_nodal_connec->getConstPointer();
5775 const int *ci=_nodal_connec_index->getConstPointer();
5776 for(int i=0;i<nbOfCells;i++,ci++)
5778 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5780 for(int j=0;j<6;j++,pt+=5,ptI++)
5782 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5783 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];
5790 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5791 ptI[1]=ptI[0]+ci[1]-ci[0];
5796 _nodal_connec->decrRef();
5797 _nodal_connec=newConn.retn();
5798 _nodal_connec_index->decrRef();
5799 _nodal_connec_index=newConnI.retn();
5806 * 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.
5807 * This method completly ignore coordinates.
5808 * \param nodeSubdived is the nodal connectivity of subdivision of edges
5809 * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5810 * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5811 * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5813 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5815 checkFullyDefined();
5816 if(getMeshDimension()!=2)
5817 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5818 int nbOfCells=getNumberOfCells();
5819 int *connI=_nodal_connec_index->getPointer();
5821 for(int i=0;i<nbOfCells;i++,connI++)
5823 int offset=descIndex[i];
5824 int nbOfEdges=descIndex[i+1]-offset;
5826 bool ddirect=desc[offset+nbOfEdges-1]>0;
5827 int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5828 int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5829 for(int j=0;j<nbOfEdges;j++)
5831 bool direct=desc[offset+j]>0;
5832 int edgeId=std::abs(desc[offset+j])-1;
5833 if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5835 int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5836 int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5837 int ref2=direct?id1:id2;
5840 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5841 newConnLgth+=nbOfSubNodes-1;
5846 std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5847 throw INTERP_KERNEL::Exception(oss.str().c_str());
5852 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5855 newConnLgth++;//+1 is for cell type
5856 connI[1]=newConnLgth;
5859 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5860 newConn->alloc(newConnLgth,1);
5861 int *work=newConn->getPointer();
5862 for(int i=0;i<nbOfCells;i++)
5864 *work++=INTERP_KERNEL::NORM_POLYGON;
5865 int offset=descIndex[i];
5866 int nbOfEdges=descIndex[i+1]-offset;
5867 for(int j=0;j<nbOfEdges;j++)
5869 bool direct=desc[offset+j]>0;
5870 int edgeId=std::abs(desc[offset+j])-1;
5872 work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5875 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5876 std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5877 work=std::copy(it,it+nbOfSubNodes-1,work);
5881 DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5884 _types.insert(INTERP_KERNEL::NORM_POLYGON);
5888 * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5889 * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5890 * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5891 * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5892 * so it can be useful to call mergeNodes() before calling this method.
5893 * \throw If \a this->getMeshDimension() <= 1.
5894 * \throw If the coordinates array is not set.
5895 * \throw If the nodal connectivity of cells is not defined.
5897 void MEDCouplingUMesh::convertDegeneratedCells()
5899 checkFullyDefined();
5900 if(getMeshDimension()<=1)
5901 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5902 int nbOfCells=getNumberOfCells();
5905 int initMeshLgth=getMeshLength();
5906 int *conn=_nodal_connec->getPointer();
5907 int *index=_nodal_connec_index->getPointer();
5911 for(int i=0;i<nbOfCells;i++)
5913 lgthOfCurCell=index[i+1]-posOfCurCell;
5914 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5916 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5917 conn+newPos+1,newLgth);
5918 conn[newPos]=newType;
5920 posOfCurCell=index[i+1];
5923 if(newPos!=initMeshLgth)
5924 _nodal_connec->reAlloc(newPos);
5929 * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5930 * A cell is considered to be oriented correctly if an angle between its
5931 * normal vector and a given vector is less than \c PI / \c 2.
5932 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5934 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5936 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5937 * is not cleared before filling in.
5938 * \throw If \a this->getMeshDimension() != 2.
5939 * \throw If \a this->getSpaceDimension() != 3.
5941 * \if ENABLE_EXAMPLES
5942 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5943 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5946 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
5948 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5949 throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5950 int nbOfCells=getNumberOfCells();
5951 const int *conn=_nodal_connec->getConstPointer();
5952 const int *connI=_nodal_connec_index->getConstPointer();
5953 const double *coordsPtr=_coords->getConstPointer();
5954 for(int i=0;i<nbOfCells;i++)
5956 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5957 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5959 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5960 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5967 * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5968 * considered to be oriented correctly if an angle between its normal vector and a
5969 * given vector is less than \c PI / \c 2.
5970 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5972 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5974 * \throw If \a this->getMeshDimension() != 2.
5975 * \throw If \a this->getSpaceDimension() != 3.
5977 * \if ENABLE_EXAMPLES
5978 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5979 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5982 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
5984 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5985 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5986 int nbOfCells=getNumberOfCells();
5987 int *conn=_nodal_connec->getPointer();
5988 const int *connI=_nodal_connec_index->getConstPointer();
5989 const double *coordsPtr=_coords->getConstPointer();
5990 bool isModified=false;
5991 for(int i=0;i<nbOfCells;i++)
5993 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5994 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5996 bool isQuadratic(INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic());
5997 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6002 std::vector<int> tmp(connI[i+1]-connI[i]-2);
6003 std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
6004 std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
6008 int sz(((int)(connI[i+1]-connI[i]-1))/2);
6009 std::vector<int> tmp0(sz-1),tmp1(sz);
6010 std::copy(conn+connI[i]+2,conn+connI[i]+1+sz,tmp0.rbegin());
6011 std::copy(conn+connI[i]+1+sz,conn+connI[i+1],tmp1.rbegin());
6012 std::copy(tmp0.begin(),tmp0.end(),conn+connI[i]+2);
6013 std::copy(tmp1.begin(),tmp1.end(),conn+connI[i]+1+sz);
6019 _nodal_connec->declareAsNew();
6024 * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
6025 * oriented facets. The normal vector of the facet should point out of the cell.
6026 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6027 * is not cleared before filling in.
6028 * \throw If \a this->getMeshDimension() != 3.
6029 * \throw If \a this->getSpaceDimension() != 3.
6030 * \throw If the coordinates array is not set.
6031 * \throw If the nodal connectivity of cells is not defined.
6033 * \if ENABLE_EXAMPLES
6034 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6035 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6038 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
6040 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6041 throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
6042 int nbOfCells=getNumberOfCells();
6043 const int *conn=_nodal_connec->getConstPointer();
6044 const int *connI=_nodal_connec_index->getConstPointer();
6045 const double *coordsPtr=_coords->getConstPointer();
6046 for(int i=0;i<nbOfCells;i++)
6048 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6049 if(type==INTERP_KERNEL::NORM_POLYHED)
6051 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6058 * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6060 * \throw If \a this->getMeshDimension() != 3.
6061 * \throw If \a this->getSpaceDimension() != 3.
6062 * \throw If the coordinates array is not set.
6063 * \throw If the nodal connectivity of cells is not defined.
6064 * \throw If the reparation fails.
6066 * \if ENABLE_EXAMPLES
6067 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6068 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6070 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6072 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
6074 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6075 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6076 int nbOfCells=getNumberOfCells();
6077 int *conn=_nodal_connec->getPointer();
6078 const int *connI=_nodal_connec_index->getConstPointer();
6079 const double *coordsPtr=_coords->getConstPointer();
6080 for(int i=0;i<nbOfCells;i++)
6082 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6083 if(type==INTERP_KERNEL::NORM_POLYHED)
6087 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6088 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6090 catch(INTERP_KERNEL::Exception& e)
6092 std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6093 throw INTERP_KERNEL::Exception(oss.str().c_str());
6101 * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6102 * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6103 * according to which the first facet of the cell should be oriented to have the normal vector
6104 * pointing out of cell.
6105 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6106 * cells. The caller is to delete this array using decrRef() as it is no more
6108 * \throw If \a this->getMeshDimension() != 3.
6109 * \throw If \a this->getSpaceDimension() != 3.
6110 * \throw If the coordinates array is not set.
6111 * \throw If the nodal connectivity of cells is not defined.
6113 * \if ENABLE_EXAMPLES
6114 * \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6115 * \ref py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6117 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6119 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6121 const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6122 if(getMeshDimension()!=3)
6123 throw INTERP_KERNEL::Exception(msg);
6124 int spaceDim=getSpaceDimension();
6126 throw INTERP_KERNEL::Exception(msg);
6128 int nbOfCells=getNumberOfCells();
6129 int *conn=_nodal_connec->getPointer();
6130 const int *connI=_nodal_connec_index->getConstPointer();
6131 const double *coo=getCoords()->getConstPointer();
6132 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6133 for(int i=0;i<nbOfCells;i++)
6135 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6136 if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6138 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6140 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6141 cells->pushBackSilent(i);
6145 return cells.retn();
6149 * This method is a faster method to correct orientation of all 3D cells in \a this.
6150 * 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.
6151 * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6153 * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6154 * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons,
6156 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6158 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6159 throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6160 int nbOfCells=getNumberOfCells();
6161 int *conn=_nodal_connec->getPointer();
6162 const int *connI=_nodal_connec_index->getConstPointer();
6163 const double *coordsPtr=_coords->getConstPointer();
6164 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6165 for(int i=0;i<nbOfCells;i++)
6167 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6170 case INTERP_KERNEL::NORM_TETRA4:
6172 if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6174 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6175 ret->pushBackSilent(i);
6179 case INTERP_KERNEL::NORM_PYRA5:
6181 if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6183 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6184 ret->pushBackSilent(i);
6188 case INTERP_KERNEL::NORM_PENTA6:
6189 case INTERP_KERNEL::NORM_HEXA8:
6190 case INTERP_KERNEL::NORM_HEXGP12:
6192 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6194 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6195 ret->pushBackSilent(i);
6199 case INTERP_KERNEL::NORM_POLYHED:
6201 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6203 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6204 ret->pushBackSilent(i);
6209 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 !");
6217 * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6218 * If it is not the case an exception will be thrown.
6219 * This method is fast because the first cell of \a this is used to compute the plane.
6220 * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6221 * \param pos output of size at least 3 used to store a point owned of searched plane.
6223 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6225 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6226 throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6227 const int *conn=_nodal_connec->getConstPointer();
6228 const int *connI=_nodal_connec_index->getConstPointer();
6229 const double *coordsPtr=_coords->getConstPointer();
6230 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6231 std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6235 * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6236 * cells. Currently cells of the following types are treated:
6237 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6238 * For a cell of other type an exception is thrown.
6239 * Space dimension of a 2D mesh can be either 2 or 3.
6240 * The Edge Ratio of a cell \f$t\f$ is:
6241 * \f$\frac{|t|_\infty}{|t|_0}\f$,
6242 * where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6243 * the smallest edge lengths of \f$t\f$.
6244 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6245 * cells and one time, lying on \a this mesh. The caller is to delete this
6246 * field using decrRef() as it is no more needed.
6247 * \throw If the coordinates array is not set.
6248 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6249 * \throw If the connectivity data array has more than one component.
6250 * \throw If the connectivity data array has a named component.
6251 * \throw If the connectivity index data array has more than one component.
6252 * \throw If the connectivity index data array has a named component.
6253 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6254 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6255 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6257 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6260 int spaceDim=getSpaceDimension();
6261 int meshDim=getMeshDimension();
6262 if(spaceDim!=2 && spaceDim!=3)
6263 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6264 if(meshDim!=2 && meshDim!=3)
6265 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6266 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6268 int nbOfCells=getNumberOfCells();
6269 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6270 arr->alloc(nbOfCells,1);
6271 double *pt=arr->getPointer();
6272 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6273 const int *conn=_nodal_connec->getConstPointer();
6274 const int *connI=_nodal_connec_index->getConstPointer();
6275 const double *coo=_coords->getConstPointer();
6277 for(int i=0;i<nbOfCells;i++,pt++)
6279 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6282 case INTERP_KERNEL::NORM_TRI3:
6284 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6285 *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6288 case INTERP_KERNEL::NORM_QUAD4:
6290 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6291 *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6294 case INTERP_KERNEL::NORM_TETRA4:
6296 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6297 *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6301 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6303 conn+=connI[i+1]-connI[i];
6305 ret->setName("EdgeRatio");
6306 ret->synchronizeTimeWithSupport();
6311 * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6312 * cells. Currently cells of the following types are treated:
6313 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6314 * For a cell of other type an exception is thrown.
6315 * Space dimension of a 2D mesh can be either 2 or 3.
6316 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6317 * cells and one time, lying on \a this mesh. The caller is to delete this
6318 * field using decrRef() as it is no more needed.
6319 * \throw If the coordinates array is not set.
6320 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6321 * \throw If the connectivity data array has more than one component.
6322 * \throw If the connectivity data array has a named component.
6323 * \throw If the connectivity index data array has more than one component.
6324 * \throw If the connectivity index data array has a named component.
6325 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6326 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6327 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6329 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6332 int spaceDim=getSpaceDimension();
6333 int meshDim=getMeshDimension();
6334 if(spaceDim!=2 && spaceDim!=3)
6335 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6336 if(meshDim!=2 && meshDim!=3)
6337 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6338 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6340 int nbOfCells=getNumberOfCells();
6341 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6342 arr->alloc(nbOfCells,1);
6343 double *pt=arr->getPointer();
6344 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6345 const int *conn=_nodal_connec->getConstPointer();
6346 const int *connI=_nodal_connec_index->getConstPointer();
6347 const double *coo=_coords->getConstPointer();
6349 for(int i=0;i<nbOfCells;i++,pt++)
6351 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6354 case INTERP_KERNEL::NORM_TRI3:
6356 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6357 *pt=INTERP_KERNEL::triAspectRatio(tmp);
6360 case INTERP_KERNEL::NORM_QUAD4:
6362 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6363 *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6366 case INTERP_KERNEL::NORM_TETRA4:
6368 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6369 *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6373 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6375 conn+=connI[i+1]-connI[i];
6377 ret->setName("AspectRatio");
6378 ret->synchronizeTimeWithSupport();
6383 * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6384 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6385 * treated: INTERP_KERNEL::NORM_QUAD4.
6386 * For a cell of other type an exception is thrown.
6387 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6388 * cells and one time, lying on \a this mesh. The caller is to delete this
6389 * field using decrRef() as it is no more needed.
6390 * \throw If the coordinates array is not set.
6391 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6392 * \throw If the connectivity data array has more than one component.
6393 * \throw If the connectivity data array has a named component.
6394 * \throw If the connectivity index data array has more than one component.
6395 * \throw If the connectivity index data array has a named component.
6396 * \throw If \a this->getMeshDimension() != 2.
6397 * \throw If \a this->getSpaceDimension() != 3.
6398 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6400 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6403 int spaceDim=getSpaceDimension();
6404 int meshDim=getMeshDimension();
6406 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6408 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6409 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6411 int nbOfCells=getNumberOfCells();
6412 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6413 arr->alloc(nbOfCells,1);
6414 double *pt=arr->getPointer();
6415 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6416 const int *conn=_nodal_connec->getConstPointer();
6417 const int *connI=_nodal_connec_index->getConstPointer();
6418 const double *coo=_coords->getConstPointer();
6420 for(int i=0;i<nbOfCells;i++,pt++)
6422 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6425 case INTERP_KERNEL::NORM_QUAD4:
6427 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6428 *pt=INTERP_KERNEL::quadWarp(tmp);
6432 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6434 conn+=connI[i+1]-connI[i];
6436 ret->setName("Warp");
6437 ret->synchronizeTimeWithSupport();
6443 * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6444 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6445 * treated: INTERP_KERNEL::NORM_QUAD4.
6446 * For a cell of other type an exception is thrown.
6447 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6448 * cells and one time, lying on \a this mesh. The caller is to delete this
6449 * field using decrRef() as it is no more needed.
6450 * \throw If the coordinates array is not set.
6451 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6452 * \throw If the connectivity data array has more than one component.
6453 * \throw If the connectivity data array has a named component.
6454 * \throw If the connectivity index data array has more than one component.
6455 * \throw If the connectivity index data array has a named component.
6456 * \throw If \a this->getMeshDimension() != 2.
6457 * \throw If \a this->getSpaceDimension() != 3.
6458 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6460 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6463 int spaceDim=getSpaceDimension();
6464 int meshDim=getMeshDimension();
6466 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6468 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6469 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6471 int nbOfCells=getNumberOfCells();
6472 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6473 arr->alloc(nbOfCells,1);
6474 double *pt=arr->getPointer();
6475 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6476 const int *conn=_nodal_connec->getConstPointer();
6477 const int *connI=_nodal_connec_index->getConstPointer();
6478 const double *coo=_coords->getConstPointer();
6480 for(int i=0;i<nbOfCells;i++,pt++)
6482 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6485 case INTERP_KERNEL::NORM_QUAD4:
6487 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6488 *pt=INTERP_KERNEL::quadSkew(tmp);
6492 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6494 conn+=connI[i+1]-connI[i];
6496 ret->setName("Skew");
6497 ret->synchronizeTimeWithSupport();
6502 * This method aggregate the bbox of each cell and put it into bbox parameter.
6504 * \param [in] arcDetEps - a parameter specifying in case of 2D quadratic polygon cell the detection limit between linear and arc circle. (By default 1e-12)
6505 * For all other cases this input parameter is ignored.
6506 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6508 * \throw If \a this is not fully set (coordinates and connectivity).
6509 * \throw If a cell in \a this has no valid nodeId.
6510 * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6512 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6514 int mDim(getMeshDimension()),sDim(getSpaceDimension());
6515 if((mDim==3 && sDim==3) || (mDim==2 && sDim==3) || (mDim==1 && sDim==1) || ( mDim==1 && sDim==3)) // Compute refined boundary box for quadratic elements only in 2D.
6516 return getBoundingBoxForBBTreeFast();
6517 if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6519 bool presenceOfQuadratic(false);
6520 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6522 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6523 if(cm.isQuadratic())
6524 presenceOfQuadratic=true;
6526 if(!presenceOfQuadratic)
6527 return getBoundingBoxForBBTreeFast();
6528 if(mDim==2 && sDim==2)
6529 return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6531 return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6533 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getBoundingBoxForBBTree : Managed dimensions are (mDim=1,sDim=1), (mDim=1,sDim=2), (mDim=1,sDim=3), (mDim=2,sDim=2), (mDim=2,sDim=3) and (mDim=3,sDim=3) !");
6537 * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6538 * So meshes having quadratic cells the computed bounding boxes can be invalid !
6540 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6542 * \throw If \a this is not fully set (coordinates and connectivity).
6543 * \throw If a cell in \a this has no valid nodeId.
6545 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6547 checkFullyDefined();
6548 int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6549 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6550 double *bbox(ret->getPointer());
6551 for(int i=0;i<nbOfCells*spaceDim;i++)
6553 bbox[2*i]=std::numeric_limits<double>::max();
6554 bbox[2*i+1]=-std::numeric_limits<double>::max();
6556 const double *coordsPtr(_coords->getConstPointer());
6557 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6558 for(int i=0;i<nbOfCells;i++)
6560 int offset=connI[i]+1;
6561 int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6562 for(int j=0;j<nbOfNodesForCell;j++)
6564 int nodeId=conn[offset+j];
6565 if(nodeId>=0 && nodeId<nbOfNodes)
6567 for(int k=0;k<spaceDim;k++)
6569 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6570 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6577 std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6578 throw INTERP_KERNEL::Exception(oss.str().c_str());
6585 * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6586 * useful for 2D meshes having quadratic cells
6587 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6588 * the two extremities of the arc of circle).
6590 * \param [in] arcDetEps - a parameter specifying in case of 2D quadratic polygon cell the detection limit between linear and arc circle. (By default 1e-12)
6591 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6592 * \throw If \a this is not fully defined.
6593 * \throw If \a this is not a mesh with meshDimension equal to 2.
6594 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6595 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6597 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6599 checkFullyDefined();
6600 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6601 if(spaceDim!=2 || mDim!=2)
6602 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic : This method should be applied on mesh with mesh dimension equal to 2 and space dimension also equal to 2!");
6603 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6604 double *bbox(ret->getPointer());
6605 const double *coords(_coords->getConstPointer());
6606 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6607 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6609 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6610 int sz(connI[1]-connI[0]-1);
6611 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6612 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6613 INTERP_KERNEL::QuadraticPolygon *pol(0);
6614 for(int j=0;j<sz;j++)
6616 int nodeId(conn[*connI+1+j]);
6617 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6619 if(!cm.isQuadratic())
6620 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6622 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6623 INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6624 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax();
6630 * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6631 * useful for 2D meshes having quadratic cells
6632 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6633 * the two extremities of the arc of circle).
6635 * \param [in] arcDetEps - a parameter specifying in case of 2D quadratic polygon cell the detection limit between linear and arc circle. (By default 1e-12)
6636 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6637 * \throw If \a this is not fully defined.
6638 * \throw If \a this is not a mesh with meshDimension equal to 1.
6639 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6640 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6642 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6644 checkFullyDefined();
6645 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6646 if(spaceDim!=2 || mDim!=1)
6647 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic : This method should be applied on mesh with mesh dimension equal to 1 and space dimension also equal to 2!");
6648 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6649 double *bbox(ret->getPointer());
6650 const double *coords(_coords->getConstPointer());
6651 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6652 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6654 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6655 int sz(connI[1]-connI[0]-1);
6656 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6657 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6658 INTERP_KERNEL::Edge *edge(0);
6659 for(int j=0;j<sz;j++)
6661 int nodeId(conn[*connI+1+j]);
6662 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6664 if(!cm.isQuadratic())
6665 edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6667 edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6668 const INTERP_KERNEL::Bounds& b(edge->getBounds());
6669 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6676 namespace ParaMEDMEMImpl
6681 ConnReader(const int *c, int val):_conn(c),_val(val) { }
6682 bool operator() (const int& pos) { return _conn[pos]!=_val; }
6691 ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6692 bool operator() (const int& pos) { return _conn[pos]==_val; }
6702 * This method expects that \a this is sorted by types. If not an exception will be thrown.
6703 * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6704 * \a this is composed in cell types.
6705 * The returned array is of size 3*n where n is the number of different types present in \a this.
6706 * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here.
6707 * This parameter is kept only for compatibility with other methode listed above.
6709 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6711 checkConnectivityFullyDefined();
6712 const int *conn=_nodal_connec->getConstPointer();
6713 const int *connI=_nodal_connec_index->getConstPointer();
6714 const int *work=connI;
6715 int nbOfCells=getNumberOfCells();
6716 std::size_t n=getAllGeoTypes().size();
6717 std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6718 std::set<INTERP_KERNEL::NormalizedCellType> types;
6719 for(std::size_t i=0;work!=connI+nbOfCells;i++)
6721 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6722 if(types.find(typ)!=types.end())
6724 std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6725 oss << " is not contiguous !";
6726 throw INTERP_KERNEL::Exception(oss.str().c_str());
6730 const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6731 ret[3*i+1]=(int)std::distance(work,work2);
6738 * This method is used to check that this has contiguous cell type in same order than described in \a code.
6739 * only for types cell, type node is not managed.
6740 * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6741 * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6742 * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6743 * If 2 or more same geometric type is in \a code and exception is thrown too.
6745 * This method firstly checks
6746 * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6747 * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6748 * an exception is thrown too.
6750 * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6751 * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown
6752 * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6754 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6757 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6758 std::size_t sz=code.size();
6761 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6762 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6764 bool isNoPflUsed=true;
6765 for(std::size_t i=0;i<n;i++)
6766 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6768 types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6770 if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6771 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6772 isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6775 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6778 if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6779 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6780 if(types.size()==_types.size())
6783 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6785 int *retPtr=ret->getPointer();
6786 const int *connI=_nodal_connec_index->getConstPointer();
6787 const int *conn=_nodal_connec->getConstPointer();
6788 int nbOfCells=getNumberOfCells();
6791 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6793 i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6794 int offset=(int)std::distance(connI,i);
6795 const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6796 int nbOfCellsOfCurType=(int)std::distance(i,j);
6797 if(code[3*kk+2]==-1)
6798 for(int k=0;k<nbOfCellsOfCurType;k++)
6802 int idInIdsPerType=code[3*kk+2];
6803 if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6805 const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6808 zePfl->checkAllocated();
6809 if(zePfl->getNumberOfComponents()==1)
6811 for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6813 if(*k>=0 && *k<nbOfCellsOfCurType)
6814 *retPtr=(*k)+offset;
6817 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6818 oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6819 throw INTERP_KERNEL::Exception(oss.str().c_str());
6824 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6827 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6831 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6832 oss << " should be in [0," << idsPerType.size() << ") !";
6833 throw INTERP_KERNEL::Exception(oss.str().c_str());
6842 * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6843 * 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.
6844 * 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.
6845 * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6847 * \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.
6848 * \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,
6849 * \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6850 * \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.
6851 * This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6852 * \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
6854 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6857 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6858 if(profile->getNumberOfComponents()!=1)
6859 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6860 checkConnectivityFullyDefined();
6861 const int *conn=_nodal_connec->getConstPointer();
6862 const int *connI=_nodal_connec_index->getConstPointer();
6863 int nbOfCells=getNumberOfCells();
6864 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6865 std::vector<int> typeRangeVals(1);
6866 for(const int *i=connI;i!=connI+nbOfCells;)
6868 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6869 if(std::find(types.begin(),types.end(),curType)!=types.end())
6871 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6873 types.push_back(curType);
6874 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6875 typeRangeVals.push_back((int)std::distance(connI,i));
6878 DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6879 profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6880 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6881 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6882 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6884 int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6885 code.resize(3*nbOfCastsFinal);
6886 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6887 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6888 for(int i=0;i<nbOfCastsFinal;i++)
6890 int castId=castsPresent->getIJ(i,0);
6891 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6892 idsInPflPerType2.push_back(tmp3);
6893 code[3*i]=(int)types[castId];
6894 code[3*i+1]=tmp3->getNumberOfTuples();
6895 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6896 if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6898 tmp4->copyStringInfoFrom(*profile);
6899 idsPerType2.push_back(tmp4);
6900 code[3*i+2]=(int)idsPerType2.size()-1;
6907 std::size_t sz2=idsInPflPerType2.size();
6908 idsInPflPerType.resize(sz2);
6909 for(std::size_t i=0;i<sz2;i++)
6911 DataArrayInt *locDa=idsInPflPerType2[i];
6913 idsInPflPerType[i]=locDa;
6915 std::size_t sz=idsPerType2.size();
6916 idsPerType.resize(sz);
6917 for(std::size_t i=0;i<sz;i++)
6919 DataArrayInt *locDa=idsPerType2[i];
6921 idsPerType[i]=locDa;
6926 * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6927 * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6928 * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6929 * 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.
6931 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
6933 checkFullyDefined();
6934 nM1LevMesh->checkFullyDefined();
6935 if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6936 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6937 if(_coords!=nM1LevMesh->getCoords())
6938 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6939 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6940 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6941 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6942 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6943 desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6944 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6945 tmp->setConnectivity(tmp0,tmp1);
6946 tmp->renumberCells(ret0->getConstPointer(),false);
6947 revDesc=tmp->getNodalConnectivity();
6948 revDescIndx=tmp->getNodalConnectivityIndex();
6949 DataArrayInt *ret=0;
6950 if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6953 ret->getMaxValue(tmp2);
6955 std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6956 throw INTERP_KERNEL::Exception(oss.str().c_str());
6961 revDescIndx->incrRef();
6964 meshnM1Old2New=ret0;
6969 * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6970 * necessary for writing the mesh to MED file. Additionally returns a permutation array
6971 * in "Old to New" mode.
6972 * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6973 * this array using decrRef() as it is no more needed.
6974 * \throw If the nodal connectivity of cells is not defined.
6976 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
6978 checkConnectivityFullyDefined();
6979 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6980 renumberCells(ret->getConstPointer(),false);
6985 * This methods checks that cells are sorted by their types.
6986 * This method makes asumption (no check) that connectivity is correctly set before calling.
6988 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6990 checkFullyDefined();
6991 const int *conn=_nodal_connec->getConstPointer();
6992 const int *connI=_nodal_connec_index->getConstPointer();
6993 int nbOfCells=getNumberOfCells();
6994 std::set<INTERP_KERNEL::NormalizedCellType> types;
6995 for(const int *i=connI;i!=connI+nbOfCells;)
6997 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6998 if(types.find(curType)!=types.end())
7000 types.insert(curType);
7001 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7007 * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
7008 * The geometric type order is specified by MED file.
7010 * \sa MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
7012 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
7014 return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7018 * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
7019 * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
7020 * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
7021 * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
7023 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7025 checkFullyDefined();
7026 const int *conn=_nodal_connec->getConstPointer();
7027 const int *connI=_nodal_connec_index->getConstPointer();
7028 int nbOfCells=getNumberOfCells();
7032 std::set<INTERP_KERNEL::NormalizedCellType> sg;
7033 for(const int *i=connI;i!=connI+nbOfCells;)
7035 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7036 const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
7037 if(isTypeExists!=orderEnd)
7039 int pos=(int)std::distance(orderBg,isTypeExists);
7043 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7047 if(sg.find(curType)==sg.end())
7049 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7060 * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
7061 * 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
7062 * 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'.
7064 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
7066 checkConnectivityFullyDefined();
7067 int nbOfCells=getNumberOfCells();
7068 const int *conn=_nodal_connec->getConstPointer();
7069 const int *connI=_nodal_connec_index->getConstPointer();
7070 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
7071 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
7072 tmpa->alloc(nbOfCells,1);
7073 tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
7074 tmpb->fillWithZero();
7075 int *tmp=tmpa->getPointer();
7076 int *tmp2=tmpb->getPointer();
7077 for(const int *i=connI;i!=connI+nbOfCells;i++)
7079 const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
7082 int pos=(int)std::distance(orderBg,where);
7084 tmp[std::distance(connI,i)]=pos;
7088 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
7089 std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
7090 oss << " has a type " << cm.getRepr() << " not in input array of type !";
7091 throw INTERP_KERNEL::Exception(oss.str().c_str());
7094 nbPerType=tmpb.retn();
7099 * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7101 * \return a new object containing the old to new correspondance.
7103 * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7105 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7107 return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7111 * 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.
7112 * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7113 * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7114 * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7116 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7118 DataArrayInt *nbPerType=0;
7119 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7120 nbPerType->decrRef();
7121 return tmpa->buildPermArrPerLevel();
7125 * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7126 * The number of cells remains unchanged after the call of this method.
7127 * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7128 * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7130 * \return the array giving the correspondance old to new.
7132 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7134 checkFullyDefined();
7136 const int *conn=_nodal_connec->getConstPointer();
7137 const int *connI=_nodal_connec_index->getConstPointer();
7138 int nbOfCells=getNumberOfCells();
7139 std::vector<INTERP_KERNEL::NormalizedCellType> types;
7140 for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7141 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7143 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7144 types.push_back(curType);
7145 for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7147 DataArrayInt *ret=DataArrayInt::New();
7148 ret->alloc(nbOfCells,1);
7149 int *retPtr=ret->getPointer();
7150 std::fill(retPtr,retPtr+nbOfCells,-1);
7152 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7154 for(const int *i=connI;i!=connI+nbOfCells;i++)
7155 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7156 retPtr[std::distance(connI,i)]=newCellId++;
7158 renumberCells(retPtr,false);
7163 * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7164 * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7165 * This method makes asumption that connectivity is correctly set before calling.
7167 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7169 checkConnectivityFullyDefined();
7170 const int *conn=_nodal_connec->getConstPointer();
7171 const int *connI=_nodal_connec_index->getConstPointer();
7172 int nbOfCells=getNumberOfCells();
7173 std::vector<MEDCouplingUMesh *> ret;
7174 for(const int *i=connI;i!=connI+nbOfCells;)
7176 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7177 int beginCellId=(int)std::distance(connI,i);
7178 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7179 int endCellId=(int)std::distance(connI,i);
7180 int sz=endCellId-beginCellId;
7181 int *cells=new int[sz];
7182 for(int j=0;j<sz;j++)
7183 cells[j]=beginCellId+j;
7184 MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7192 * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7193 * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7194 * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7196 * \return a newly allocated instance, that the caller must manage.
7197 * \throw If \a this contains more than one geometric type.
7198 * \throw If the nodal connectivity of \a this is not fully defined.
7199 * \throw If the internal data is not coherent.
7201 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7203 checkConnectivityFullyDefined();
7204 if(_types.size()!=1)
7205 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7206 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7207 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7208 ret->setCoords(getCoords());
7209 MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7212 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7213 retC->setNodalConnectivity(c);
7217 MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7219 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7220 DataArrayInt *c=0,*ci=0;
7221 convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7222 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7223 retD->setNodalConnectivity(cs,cis);
7228 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7230 checkConnectivityFullyDefined();
7231 if(_types.size()!=1)
7232 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7233 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7234 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7237 std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7238 oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7239 throw INTERP_KERNEL::Exception(oss.str().c_str());
7241 int nbCells=getNumberOfCells();
7243 int nbNodesPerCell=(int)cm.getNumberOfNodes();
7244 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7245 int *outPtr=connOut->getPointer();
7246 const int *conn=_nodal_connec->begin();
7247 const int *connI=_nodal_connec_index->begin();
7249 for(int i=0;i<nbCells;i++,connI++)
7251 if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7252 outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7255 std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : there something wrong in cell #" << i << " ! The type of cell is not those expected, or the length of nodal connectivity is not those expected (" << nbNodesPerCell-1 << ") !";
7256 throw INTERP_KERNEL::Exception(oss.str().c_str());
7259 return connOut.retn();
7262 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7264 static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7265 checkConnectivityFullyDefined();
7266 if(_types.size()!=1)
7267 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7268 int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7270 throw INTERP_KERNEL::Exception(msg0);
7271 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7272 c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7273 int *cp(c->getPointer()),*cip(ci->getPointer());
7274 const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7276 for(int i=0;i<nbCells;i++,cip++,incip++)
7278 int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7279 int delta(stop-strt);
7282 if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7283 cp=std::copy(incp+strt,incp+stop,cp);
7285 throw INTERP_KERNEL::Exception(msg0);
7288 throw INTERP_KERNEL::Exception(msg0);
7289 cip[1]=cip[0]+delta;
7291 nodalConn=c.retn(); nodalConnIndex=ci.retn();
7295 * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7296 * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7297 * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7298 * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7299 * are not used here to avoid the build of big permutation array.
7301 * \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
7302 * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7303 * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7304 * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7305 * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7306 * output array gives for each chunck of same type the corresponding mesh id in \b ms.
7307 * \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
7308 * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7310 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7311 DataArrayInt *&szOfCellGrpOfSameType,
7312 DataArrayInt *&idInMsOfCellGrpOfSameType)
7314 std::vector<const MEDCouplingUMesh *> ms2;
7315 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7318 (*it)->checkConnectivityFullyDefined();
7322 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7323 const DataArrayDouble *refCoo=ms2[0]->getCoords();
7324 int meshDim=ms2[0]->getMeshDimension();
7325 std::vector<const MEDCouplingUMesh *> m1ssm;
7326 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7328 std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7329 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7331 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7332 ret1->alloc(0,1); ret2->alloc(0,1);
7333 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7335 if(meshDim!=(*it)->getMeshDimension())
7336 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7337 if(refCoo!=(*it)->getCoords())
7338 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7339 std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7340 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7341 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7342 for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7344 MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7345 m1ssmSingleAuto.push_back(singleCell);
7346 m1ssmSingle.push_back(singleCell);
7347 ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7350 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7351 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7352 std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7353 for(std::size_t i=0;i<m1ssm.size();i++)
7354 m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7355 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7356 szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7357 idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7362 * This method returns a newly created DataArrayInt instance.
7363 * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7365 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7367 checkFullyDefined();
7368 const int *conn=_nodal_connec->getConstPointer();
7369 const int *connIndex=_nodal_connec_index->getConstPointer();
7370 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7371 for(const int *w=begin;w!=end;w++)
7372 if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7373 ret->pushBackSilent(*w);
7378 * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7379 * are in [0:getNumberOfCells())
7381 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7383 checkFullyDefined();
7384 const int *conn=_nodal_connec->getConstPointer();
7385 const int *connI=_nodal_connec_index->getConstPointer();
7386 int nbOfCells=getNumberOfCells();
7387 std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7388 int *tmp=new int[nbOfCells];
7389 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7392 for(const int *i=connI;i!=connI+nbOfCells;i++)
7393 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7394 tmp[std::distance(connI,i)]=j++;
7396 DataArrayInt *ret=DataArrayInt::New();
7397 ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7398 ret->copyStringInfoFrom(*da);
7399 int *retPtr=ret->getPointer();
7400 const int *daPtr=da->getConstPointer();
7401 int nbOfElems=da->getNbOfElems();
7402 for(int k=0;k<nbOfElems;k++)
7403 retPtr[k]=tmp[daPtr[k]];
7409 * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7410 * This method \b works \b for mesh sorted by type.
7411 * cells whose ids is in 'idsPerGeoType' array.
7412 * This method conserves coords and name of mesh.
7414 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7416 std::vector<int> code=getDistributionOfTypes();
7417 std::size_t nOfTypesInThis=code.size()/3;
7418 int sz=0,szOfType=0;
7419 for(std::size_t i=0;i<nOfTypesInThis;i++)
7424 szOfType=code[3*i+1];
7426 for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7427 if(*work<0 || *work>=szOfType)
7429 std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7430 oss << ". It should be in [0," << szOfType << ") !";
7431 throw INTERP_KERNEL::Exception(oss.str().c_str());
7433 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7434 int *idsPtr=idsTokeep->getPointer();
7436 for(std::size_t i=0;i<nOfTypesInThis;i++)
7439 for(int j=0;j<code[3*i+1];j++)
7442 idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7443 offset+=code[3*i+1];
7445 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7446 ret->copyTinyInfoFrom(this);
7451 * This method returns a vector of size 'this->getNumberOfCells()'.
7452 * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7454 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7456 int ncell=getNumberOfCells();
7457 std::vector<bool> ret(ncell);
7458 const int *cI=getNodalConnectivityIndex()->getConstPointer();
7459 const int *c=getNodalConnectivity()->getConstPointer();
7460 for(int i=0;i<ncell;i++)
7462 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7463 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7464 ret[i]=cm.isQuadratic();
7470 * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7472 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7474 if(other->getType()!=UNSTRUCTURED)
7475 throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7476 const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7477 return MergeUMeshes(this,otherC);
7481 * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7482 * computed by averaging coordinates of cell nodes, so this method is not a right
7483 * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7484 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7485 * this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7486 * components. The caller is to delete this array using decrRef() as it is
7488 * \throw If the coordinates array is not set.
7489 * \throw If the nodal connectivity of cells is not defined.
7490 * \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7492 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7494 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7495 int spaceDim=getSpaceDimension();
7496 int nbOfCells=getNumberOfCells();
7497 ret->alloc(nbOfCells,spaceDim);
7498 ret->copyStringInfoFrom(*getCoords());
7499 double *ptToFill=ret->getPointer();
7500 const int *nodal=_nodal_connec->getConstPointer();
7501 const int *nodalI=_nodal_connec_index->getConstPointer();
7502 const double *coor=_coords->getConstPointer();
7503 for(int i=0;i<nbOfCells;i++)
7505 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7506 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7513 * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7514 * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the
7516 * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned
7517 * DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7519 * \sa MEDCouplingUMesh::getBarycenterAndOwner
7520 * \throw If \a this is not fully defined (coordinates and connectivity)
7521 * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7523 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7525 checkFullyDefined();
7526 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7527 int spaceDim=getSpaceDimension();
7528 int nbOfCells=getNumberOfCells();
7529 int nbOfNodes=getNumberOfNodes();
7530 ret->alloc(nbOfCells,spaceDim);
7531 double *ptToFill=ret->getPointer();
7532 const int *nodal=_nodal_connec->getConstPointer();
7533 const int *nodalI=_nodal_connec_index->getConstPointer();
7534 const double *coor=_coords->getConstPointer();
7535 for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7537 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7538 std::fill(ptToFill,ptToFill+spaceDim,0.);
7539 if(type!=INTERP_KERNEL::NORM_POLYHED)
7541 for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7543 if(*conn>=0 && *conn<nbOfNodes)
7544 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7547 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," << nbOfNodes << ") !";
7548 throw INTERP_KERNEL::Exception(oss.str().c_str());
7551 int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7552 if(nbOfNodesInCell>0)
7553 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7556 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7557 throw INTERP_KERNEL::Exception(oss.str().c_str());
7562 std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7564 for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7566 if(*it>=0 && *it<nbOfNodes)
7567 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7570 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," << nbOfNodes << ") !";
7571 throw INTERP_KERNEL::Exception(oss.str().c_str());
7575 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7578 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7579 throw INTERP_KERNEL::Exception(oss.str().c_str());
7587 * Returns a new DataArrayDouble holding barycenters of specified cells. The
7588 * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7589 * are specified via an array of cell ids.
7590 * \warning Validity of the specified cell ids is not checked!
7591 * Valid range is [ 0, \a this->getNumberOfCells() ).
7592 * \param [in] begin - an array of cell ids of interest.
7593 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7594 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7595 * end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7596 * caller is to delete this array using decrRef() as it is no more needed.
7597 * \throw If the coordinates array is not set.
7598 * \throw If the nodal connectivity of cells is not defined.
7600 * \if ENABLE_EXAMPLES
7601 * \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7602 * \ref py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7605 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7607 DataArrayDouble *ret=DataArrayDouble::New();
7608 int spaceDim=getSpaceDimension();
7609 int nbOfTuple=(int)std::distance(begin,end);
7610 ret->alloc(nbOfTuple,spaceDim);
7611 double *ptToFill=ret->getPointer();
7612 double *tmp=new double[spaceDim];
7613 const int *nodal=_nodal_connec->getConstPointer();
7614 const int *nodalI=_nodal_connec_index->getConstPointer();
7615 const double *coor=_coords->getConstPointer();
7616 for(const int *w=begin;w!=end;w++)
7618 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7619 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7627 * Returns a DataArrayDouble instance giving for each cell in \a this the equation of plane given by "a*X+b*Y+c*Z+d=0".
7628 * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7629 * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7630 * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7631 * This method is useful to detect 2D cells in 3D space that are not coplanar.
7633 * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7634 * \throw If spaceDim!=3 or meshDim!=2.
7635 * \throw If connectivity of \a this is invalid.
7636 * \throw If connectivity of a cell in \a this points to an invalid node.
7638 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7640 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7641 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7642 if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7643 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7644 ret->alloc(nbOfCells,4);
7645 double *retPtr(ret->getPointer());
7646 const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7647 const double *coor(_coords->begin());
7648 for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7650 double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7651 if(nodalI[1]-nodalI[0]>=3)
7653 for(int j=0;j<3;j++)
7655 int nodeId(nodal[nodalI[0]+1+j]);
7656 if(nodeId>=0 && nodeId<nbOfNodes)
7657 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7660 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7661 throw INTERP_KERNEL::Exception(oss.str().c_str());
7667 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7668 throw INTERP_KERNEL::Exception(oss.str().c_str());
7670 INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7671 retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7677 * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7680 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7683 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7684 da->checkAllocated();
7685 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7687 int nbOfTuples=da->getNumberOfTuples();
7688 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7689 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7690 c->alloc(2*nbOfTuples,1);
7691 cI->alloc(nbOfTuples+1,1);
7692 int *cp=c->getPointer();
7693 int *cip=cI->getPointer();
7695 for(int i=0;i<nbOfTuples;i++)
7697 *cp++=INTERP_KERNEL::NORM_POINT1;
7701 ret->setConnectivity(c,cI,true);
7705 * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7706 * Cells and nodes of
7707 * the first mesh precede cells and nodes of the second mesh within the result mesh.
7708 * \param [in] mesh1 - the first mesh.
7709 * \param [in] mesh2 - the second mesh.
7710 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7711 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7712 * is no more needed.
7713 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7714 * \throw If the coordinates array is not set in none of the meshes.
7715 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7716 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7718 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7720 std::vector<const MEDCouplingUMesh *> tmp(2);
7721 tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7722 return MergeUMeshes(tmp);
7726 * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7727 * Cells and nodes of
7728 * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7729 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7730 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7731 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7732 * is no more needed.
7733 * \throw If \a a.size() == 0.
7734 * \throw If \a a[ *i* ] == NULL.
7735 * \throw If the coordinates array is not set in none of the meshes.
7736 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7737 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7739 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7741 std::size_t sz=a.size();
7743 return MergeUMeshesLL(a);
7744 for(std::size_t ii=0;ii<sz;ii++)
7747 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7748 throw INTERP_KERNEL::Exception(oss.str().c_str());
7750 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7751 std::vector< const MEDCouplingUMesh * > aa(sz);
7753 for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7755 const MEDCouplingUMesh *cur=a[i];
7756 const DataArrayDouble *coo=cur->getCoords();
7758 spaceDim=coo->getNumberOfComponents();
7761 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7762 for(std::size_t i=0;i<sz;i++)
7764 bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7767 return MergeUMeshesLL(aa);
7772 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7775 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7776 std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7777 int meshDim=(*it)->getMeshDimension();
7778 int nbOfCells=(*it)->getNumberOfCells();
7779 int meshLgth=(*it++)->getMeshLength();
7780 for(;it!=a.end();it++)
7782 if(meshDim!=(*it)->getMeshDimension())
7783 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7784 nbOfCells+=(*it)->getNumberOfCells();
7785 meshLgth+=(*it)->getMeshLength();
7787 std::vector<const MEDCouplingPointSet *> aps(a.size());
7788 std::copy(a.begin(),a.end(),aps.begin());
7789 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7790 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7791 ret->setCoords(pts);
7792 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7793 c->alloc(meshLgth,1);
7794 int *cPtr=c->getPointer();
7795 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7796 cI->alloc(nbOfCells+1,1);
7797 int *cIPtr=cI->getPointer();
7801 for(it=a.begin();it!=a.end();it++)
7803 int curNbOfCell=(*it)->getNumberOfCells();
7804 const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7805 const int *curC=(*it)->_nodal_connec->getConstPointer();
7806 cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7807 for(int j=0;j<curNbOfCell;j++)
7809 const int *src=curC+curCI[j];
7811 for(;src!=curC+curCI[j+1];src++,cPtr++)
7819 offset+=curCI[curNbOfCell];
7820 offset2+=(*it)->getNumberOfNodes();
7823 ret->setConnectivity(c,cI,true);
7830 * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7831 * dimension and sharing the node coordinates array.
7832 * All cells of the first mesh precede all cells of the second mesh
7833 * within the result mesh.
7834 * \param [in] mesh1 - the first mesh.
7835 * \param [in] mesh2 - the second mesh.
7836 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7837 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7838 * is no more needed.
7839 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7840 * \throw If the meshes do not share the node coordinates array.
7841 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7842 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7844 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7846 std::vector<const MEDCouplingUMesh *> tmp(2);
7847 tmp[0]=mesh1; tmp[1]=mesh2;
7848 return MergeUMeshesOnSameCoords(tmp);
7852 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7853 * dimension and sharing the node coordinates array.
7854 * All cells of the *i*-th mesh precede all cells of the
7855 * (*i*+1)-th mesh within the result mesh.
7856 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7857 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7858 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7859 * is no more needed.
7860 * \throw If \a a.size() == 0.
7861 * \throw If \a a[ *i* ] == NULL.
7862 * \throw If the meshes do not share the node coordinates array.
7863 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7864 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7866 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7869 throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7870 for(std::size_t ii=0;ii<meshes.size();ii++)
7873 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7874 throw INTERP_KERNEL::Exception(oss.str().c_str());
7876 const DataArrayDouble *coords=meshes.front()->getCoords();
7877 int meshDim=meshes.front()->getMeshDimension();
7878 std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7880 int meshIndexLgth=0;
7881 for(;iter!=meshes.end();iter++)
7883 if(coords!=(*iter)->getCoords())
7884 throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7885 if(meshDim!=(*iter)->getMeshDimension())
7886 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7887 meshLgth+=(*iter)->getMeshLength();
7888 meshIndexLgth+=(*iter)->getNumberOfCells();
7890 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7891 nodal->alloc(meshLgth,1);
7892 int *nodalPtr=nodal->getPointer();
7893 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7894 nodalIndex->alloc(meshIndexLgth+1,1);
7895 int *nodalIndexPtr=nodalIndex->getPointer();
7897 for(iter=meshes.begin();iter!=meshes.end();iter++)
7899 const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7900 const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7901 int nbOfCells=(*iter)->getNumberOfCells();
7902 int meshLgth2=(*iter)->getMeshLength();
7903 nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7904 if(iter!=meshes.begin())
7905 nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7907 nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7910 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7911 ret->setName("merge");
7912 ret->setMeshDimension(meshDim);
7913 ret->setConnectivity(nodal,nodalIndex,true);
7914 ret->setCoords(coords);
7919 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7920 * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7921 * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7922 * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7923 * New" mode are returned for each input mesh.
7924 * \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7925 * \param [in] compType - specifies a cell comparison technique. For meaning of its
7926 * valid values [0,1,2], see zipConnectivityTraducer().
7927 * \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7928 * meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7929 * mesh. The caller is to delete each of the arrays using decrRef() as it is
7931 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7932 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7933 * is no more needed.
7934 * \throw If \a meshes.size() == 0.
7935 * \throw If \a meshes[ *i* ] == NULL.
7936 * \throw If the meshes do not share the node coordinates array.
7937 * \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7938 * \throw If the \a meshes are of different dimension (getMeshDimension()).
7939 * \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7940 * \throw If the nodal connectivity any of \a meshes includes an invalid id.
7942 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7944 //All checks are delegated to MergeUMeshesOnSameCoords
7945 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7946 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7947 corr.resize(meshes.size());
7948 std::size_t nbOfMeshes=meshes.size();
7950 const int *o2nPtr=o2n->getConstPointer();
7951 for(std::size_t i=0;i<nbOfMeshes;i++)
7953 DataArrayInt *tmp=DataArrayInt::New();
7954 int curNbOfCells=meshes[i]->getNumberOfCells();
7955 tmp->alloc(curNbOfCells,1);
7956 std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7957 offset+=curNbOfCells;
7958 tmp->setName(meshes[i]->getName());
7965 * Makes all given meshes share the nodal connectivity array. The common connectivity
7966 * array is created by concatenating the connectivity arrays of all given meshes. All
7967 * the given meshes must be of the same space dimension but dimension of cells **can
7968 * differ**. This method is particulary useful in MEDLoader context to build a \ref
7969 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7970 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7971 * \param [in,out] meshes - a vector of meshes to update.
7972 * \throw If any of \a meshes is NULL.
7973 * \throw If the coordinates array is not set in any of \a meshes.
7974 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7975 * \throw If \a meshes are of different space dimension.
7977 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
7979 std::size_t sz=meshes.size();
7982 std::vector< const DataArrayDouble * > coords(meshes.size());
7983 std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7984 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7988 (*it)->checkConnectivityFullyDefined();
7989 const DataArrayDouble *coo=(*it)->getCoords();
7994 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7995 oss << " has no coordinate array defined !";
7996 throw INTERP_KERNEL::Exception(oss.str().c_str());
8001 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8002 oss << " is null !";
8003 throw INTERP_KERNEL::Exception(oss.str().c_str());
8006 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
8007 std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
8008 int offset=(*it)->getNumberOfNodes();
8009 (*it++)->setCoords(res);
8010 for(;it!=meshes.end();it++)
8012 int oldNumberOfNodes=(*it)->getNumberOfNodes();
8013 (*it)->setCoords(res);
8014 (*it)->shiftNodeNumbersInConn(offset);
8015 offset+=oldNumberOfNodes;
8020 * Merges nodes coincident with a given precision within all given meshes that share
8021 * the nodal connectivity array. The given meshes **can be of different** mesh
8022 * dimension. This method is particulary useful in MEDLoader context to build a \ref
8023 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8024 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8025 * \param [in,out] meshes - a vector of meshes to update.
8026 * \param [in] eps - the precision used to detect coincident nodes (infinite norm).
8027 * \throw If any of \a meshes is NULL.
8028 * \throw If the \a meshes do not share the same node coordinates array.
8029 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8031 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
8035 std::set<const DataArrayDouble *> s;
8036 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8039 s.insert((*it)->getCoords());
8042 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 !";
8043 throw INTERP_KERNEL::Exception(oss.str().c_str());
8048 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 !";
8049 throw INTERP_KERNEL::Exception(oss.str().c_str());
8051 const DataArrayDouble *coo=*(s.begin());
8055 DataArrayInt *comm,*commI;
8056 coo->findCommonTuples(eps,-1,comm,commI);
8057 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
8058 int oldNbOfNodes=coo->getNumberOfTuples();
8060 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
8061 if(oldNbOfNodes==newNbOfNodes)
8063 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
8064 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8066 (*it)->renumberNodesInConn(o2n->getConstPointer());
8067 (*it)->setCoords(newCoords);
8072 * 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.
8073 * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
8074 * \param isQuad specifies the policy of connectivity.
8075 * @ret in/out parameter in which the result will be append
8077 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
8079 INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
8080 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
8081 ret.push_back(cm.getExtrudedType());
8082 int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
8085 case INTERP_KERNEL::NORM_POINT1:
8087 ret.push_back(connBg[1]);
8088 ret.push_back(connBg[1]+nbOfNodesPerLev);
8091 case INTERP_KERNEL::NORM_SEG2:
8093 int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
8094 ret.insert(ret.end(),conn,conn+4);
8097 case INTERP_KERNEL::NORM_SEG3:
8099 int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8100 ret.insert(ret.end(),conn,conn+8);
8103 case INTERP_KERNEL::NORM_QUAD4:
8105 int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8106 ret.insert(ret.end(),conn,conn+8);
8109 case INTERP_KERNEL::NORM_TRI3:
8111 int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8112 ret.insert(ret.end(),conn,conn+6);
8115 case INTERP_KERNEL::NORM_TRI6:
8117 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,
8118 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8119 ret.insert(ret.end(),conn,conn+15);
8122 case INTERP_KERNEL::NORM_QUAD8:
8125 connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8126 connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8127 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8129 ret.insert(ret.end(),conn,conn+20);
8132 case INTERP_KERNEL::NORM_POLYGON:
8134 std::back_insert_iterator< std::vector<int> > ii(ret);
8135 std::copy(connBg+1,connEnd,ii);
8137 std::reverse_iterator<const int *> rConnBg(connEnd);
8138 std::reverse_iterator<const int *> rConnEnd(connBg+1);
8139 std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8140 std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8141 for(std::size_t i=0;i<nbOfRadFaces;i++)
8144 int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8145 std::copy(conn,conn+4,ii);
8150 throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8155 * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8157 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8160 double v[3]={0.,0.,0.};
8161 std::size_t sz=std::distance(begin,end);
8166 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];
8167 v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8168 v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8170 double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8172 // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8173 // SEG3 forming a circle):
8174 if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8176 v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8177 for(std::size_t j=0;j<sz;j++)
8179 if (j%2) // current point i is quadratic, next point i+1 is standard
8182 ip1 = (j+1)%sz; // ip1 = "i+1"
8184 else // current point i is standard, next point i+1 is quadratic
8189 v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8190 v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8191 v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8193 ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8199 * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8201 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8203 std::vector<std::pair<int,int> > edges;
8204 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8205 const int *bgFace=begin;
8206 for(std::size_t i=0;i<nbOfFaces;i++)
8208 const int *endFace=std::find(bgFace+1,end,-1);
8209 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8210 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8212 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8213 if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8215 edges.push_back(p1);
8219 return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8223 * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8225 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8227 double vec0[3],vec1[3];
8228 std::size_t sz=std::distance(begin,end);
8230 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8231 int nbOfNodes=(int)sz/2;
8232 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8233 const double *pt0=coords+3*begin[0];
8234 const double *pt1=coords+3*begin[nbOfNodes];
8235 vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8236 return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8239 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8241 std::size_t sz=std::distance(begin,end);
8242 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8243 std::size_t nbOfNodes(sz/2);
8244 std::copy(begin,end,(int *)tmp);
8245 for(std::size_t j=1;j<nbOfNodes;j++)
8247 begin[j]=tmp[nbOfNodes-j];
8248 begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8252 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8254 std::size_t sz=std::distance(begin,end);
8256 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8257 double vec0[3],vec1[3];
8258 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8259 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];
8260 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;
8263 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8265 std::size_t sz=std::distance(begin,end);
8267 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8269 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8270 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8271 return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8275 * 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 )
8276 * 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
8279 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8280 * \param [in] coords the coordinates with nb of components exactly equal to 3
8281 * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8282 * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8283 * \param [out] res the result is put at the end of the vector without any alteration of the data.
8285 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8287 int nbFaces=std::count(begin+1,end,-1)+1;
8288 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8289 double *vPtr=v->getPointer();
8290 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8291 double *pPtr=p->getPointer();
8292 const int *stFaceConn=begin+1;
8293 for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8295 const int *endFaceConn=std::find(stFaceConn,end,-1);
8296 ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8297 stFaceConn=endFaceConn+1;
8299 pPtr=p->getPointer(); vPtr=v->getPointer();
8300 DataArrayInt *comm1=0,*commI1=0;
8301 v->findCommonTuples(eps,-1,comm1,commI1);
8302 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8303 const int *comm1Ptr=comm1->getConstPointer();
8304 const int *commI1Ptr=commI1->getConstPointer();
8305 int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8306 res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8308 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8309 mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8310 mm->finishInsertingCells();
8312 for(int i=0;i<nbOfGrps1;i++)
8314 int vecId=comm1Ptr[commI1Ptr[i]];
8315 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8316 DataArrayInt *comm2=0,*commI2=0;
8317 tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8318 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8319 const int *comm2Ptr=comm2->getConstPointer();
8320 const int *commI2Ptr=commI2->getConstPointer();
8321 int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8322 for(int j=0;j<nbOfGrps2;j++)
8324 if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8326 res->insertAtTheEnd(begin,end);
8327 res->pushBackSilent(-1);
8331 int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8332 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8333 ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8334 DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8335 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8336 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8337 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8338 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8339 const int *idsNodePtr=idsNode->getConstPointer();
8340 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];
8341 double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8342 double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8343 if(std::abs(norm)>eps)
8345 double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8346 mm3->rotate(center,vec,angle);
8348 mm3->changeSpaceDimension(2);
8349 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8350 const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8351 const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8352 int nbOfCells=mm4->getNumberOfCells();
8353 for(int k=0;k<nbOfCells;k++)
8356 for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8357 res->pushBackSilent(idsNodePtr[*work]);
8358 res->pushBackSilent(-1);
8363 res->popBackSilent();
8367 * 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
8368 * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8370 * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8371 * \param [in] coords coordinates expected to have 3 components.
8372 * \param [in] begin start of the nodal connectivity of the face.
8373 * \param [in] end end of the nodal connectivity (excluded) of the face.
8374 * \param [out] v the normalized vector of size 3
8375 * \param [out] p the pos of plane
8377 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8379 std::size_t nbPoints=std::distance(begin,end);
8381 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8382 double vec[3]={0.,0.,0.};
8384 bool refFound=false;
8385 for(;j<nbPoints-1 && !refFound;j++)
8387 vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8388 vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8389 vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8390 double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8394 vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8397 for(std::size_t i=j;i<nbPoints-1;i++)
8400 curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8401 curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8402 curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8403 double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8406 curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8407 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];
8408 norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8411 v[0]/=norm; v[1]/=norm; v[2]/=norm;
8412 *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8416 throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8420 * This method tries to obtain a well oriented polyhedron.
8421 * If the algorithm fails, an exception will be thrown.
8423 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8425 std::list< std::pair<int,int> > edgesOK,edgesFinished;
8426 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8427 std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8429 int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8430 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8431 for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8433 while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8436 std::size_t smthChanged=0;
8437 for(std::size_t i=0;i<nbOfFaces;i++)
8439 endFace=std::find(bgFace+1,end,-1);
8440 nbOfEdgesInFace=std::distance(bgFace,endFace);
8444 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8446 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8447 std::pair<int,int> p2(p1.second,p1.first);
8448 bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8449 bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8450 if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8455 std::reverse(bgFace+1,endFace);
8456 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8458 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8459 std::pair<int,int> p2(p1.second,p1.first);
8460 if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8461 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8462 if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8463 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8464 std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8465 if(it!=edgesOK.end())
8468 edgesFinished.push_back(p1);
8471 edgesOK.push_back(p1);
8478 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8480 if(!edgesOK.empty())
8481 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8482 if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8483 {//not lucky ! The first face was not correctly oriented : reorient all faces...
8485 for(std::size_t i=0;i<nbOfFaces;i++)
8487 endFace=std::find(bgFace+1,end,-1);
8488 std::reverse(bgFace+1,endFace);
8494 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8496 int nbOfNodesExpected(skin->getNumberOfNodes());
8497 const int *n2oPtr(n2o->getConstPointer());
8498 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8499 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8500 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8501 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8502 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8503 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8504 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_POLYGON;
8505 if(nbOfNodesExpected<1)
8507 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8508 *work++=n2oPtr[prevNode];
8509 for(int i=1;i<nbOfNodesExpected;i++)
8511 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8513 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8514 conn.erase(prevNode);
8517 int curNode(*(conn.begin()));
8518 *work++=n2oPtr[curNode];
8519 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8520 shar.erase(prevCell);
8523 prevCell=*(shar.begin());
8527 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8530 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8533 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8538 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8540 int nbOfNodesExpected(skin->getNumberOfNodes());
8541 int nbOfTurn(nbOfNodesExpected/2);
8542 const int *n2oPtr(n2o->getConstPointer());
8543 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8544 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8545 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8546 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8547 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8548 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8549 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_QPOLYG;
8550 if(nbOfNodesExpected<1)
8552 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8553 *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8554 for(int i=1;i<nbOfTurn;i++)
8556 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8558 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8559 conn.erase(prevNode);
8562 int curNode(*(conn.begin()));
8563 *work=n2oPtr[curNode];
8564 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8565 shar.erase(prevCell);
8568 int curCell(*(shar.begin()));
8569 work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8575 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8578 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8581 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8587 * This method makes the assumption spacedimension == meshdimension == 2.
8588 * This method works only for linear cells.
8590 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8592 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8594 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8595 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8596 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8597 int oldNbOfNodes(skin->getNumberOfNodes());
8598 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8599 int nbOfNodesExpected(skin->getNumberOfNodes());
8600 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8601 int nbCells(skin->getNumberOfCells());
8602 if(nbCells==nbOfNodesExpected)
8603 return buildUnionOf2DMeshLinear(skin,n2o);
8604 else if(2*nbCells==nbOfNodesExpected)
8605 return buildUnionOf2DMeshQuadratic(skin,n2o);
8607 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8611 * This method makes the assumption spacedimension == meshdimension == 3.
8612 * This method works only for linear cells.
8614 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8616 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8618 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8619 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8620 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8621 const int *conn=m->getNodalConnectivity()->getConstPointer();
8622 const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8623 int nbOfCells=m->getNumberOfCells();
8624 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8625 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED;
8628 work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8629 for(int i=1;i<nbOfCells;i++)
8632 work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8638 * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8639 * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8641 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8645 for(int i=0;i<nbOfNodesInCell;i++)
8646 w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8647 else if(spaceDim==2)
8649 for(int i=0;i<nbOfNodesInCell;i++)
8651 w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8656 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8659 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8661 int nbOfCells=getNumberOfCells();
8663 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8664 static const int PARAMEDMEM2VTKTYPETRADUCER[INTERP_KERNEL::NORM_MAXTYPE+1]={1,3,21,5,9,7,22,34,23,28,-1,-1,-1,-1,10,14,13,-1,12,-1,24,-1,16,27,-1,26,-1,29,-1,-1,25,42,36,4};
8665 ofs << " <" << getVTKDataSetType() << ">\n";
8666 ofs << " <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8667 ofs << " <PointData>\n" << pointData << std::endl;
8668 ofs << " </PointData>\n";
8669 ofs << " <CellData>\n" << cellData << std::endl;
8670 ofs << " </CellData>\n";
8671 ofs << " <Points>\n";
8672 if(getSpaceDimension()==3)
8673 _coords->writeVTK(ofs,8,"Points",byteData);
8676 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8677 coo->writeVTK(ofs,8,"Points",byteData);
8679 ofs << " </Points>\n";
8680 ofs << " <Cells>\n";
8681 const int *cPtr=_nodal_connec->getConstPointer();
8682 const int *cIPtr=_nodal_connec_index->getConstPointer();
8683 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8684 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8685 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8686 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8687 int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8688 int szFaceOffsets=0,szConn=0;
8689 for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8692 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8695 *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8696 w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8700 int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8701 *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8702 std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8703 *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8704 w4=std::copy(c.begin(),c.end(),w4);
8707 types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8708 types->writeVTK(ofs,8,"UInt8","types",byteData);
8709 offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8710 if(szFaceOffsets!=0)
8711 {//presence of Polyhedra
8712 connectivity->reAlloc(szConn);
8713 faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8714 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8715 w1=faces->getPointer();
8716 for(int i=0;i<nbOfCells;i++)
8717 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8719 int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8721 const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8722 for(int j=0;j<nbFaces;j++)
8724 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8725 *w1++=(int)std::distance(w6,w5);
8726 w1=std::copy(w6,w5,w1);
8730 faces->writeVTK(ofs,8,"Int32","faces",byteData);
8732 connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8733 ofs << " </Cells>\n";
8734 ofs << " </Piece>\n";
8735 ofs << " </" << getVTKDataSetType() << ">\n";
8738 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8740 stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8742 { stream << " Not set !"; return ; }
8743 stream << " Mesh dimension : " << _mesh_dim << ".";
8747 { stream << " No coordinates set !"; return ; }
8748 if(!_coords->isAllocated())
8749 { stream << " Coordinates set but not allocated !"; return ; }
8750 stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8751 stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8752 if(!_nodal_connec_index)
8753 { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8754 if(!_nodal_connec_index->isAllocated())
8755 { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8756 int lgth=_nodal_connec_index->getNumberOfTuples();
8757 int cpt=_nodal_connec_index->getNumberOfComponents();
8758 if(cpt!=1 || lgth<1)
8760 stream << std::endl << "Number of cells : " << lgth-1 << ".";
8763 std::string MEDCouplingUMesh::getVTKDataSetType() const
8765 return std::string("UnstructuredGrid");
8768 std::string MEDCouplingUMesh::getVTKFileExtension() const
8770 return std::string("vtu");
8774 * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8775 * returns a result mesh constituted by polygons.
8776 * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8777 * all nodes from m2.
8778 * The meshes should be in 2D space. In
8779 * addition, returns two arrays mapping cells of the result mesh to cells of the input
8781 * \param [in] m1 - the first input mesh which is a partitioned object. The mesh must be so that each point in the space covered by \a m1
8782 * must be covered exactly by one entity, \b no \b more. If it is not the case, some tools are available to heal the mesh (conformize2D, mergeNodes)
8783 * \param [in] m2 - the second input mesh which is a partition tool. The mesh must be so that each point in the space covered by \a m2
8784 * must be covered exactly by one entity, \b no \b more. If it is not the case, some tools are available to heal the mesh (conformize2D, mergeNodes)
8785 * \param [in] eps - precision used to detect coincident mesh entities.
8786 * \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8787 * cell an id of the cell of \a m1 it comes from. The caller is to delete
8788 * this array using decrRef() as it is no more needed.
8789 * \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8790 * cell an id of the cell of \a m2 it comes from. -1 value means that a
8791 * result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8792 * any cell of \a m2. The caller is to delete this array using decrRef() as
8793 * it is no more needed.
8794 * \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8795 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8796 * is no more needed.
8797 * \throw If the coordinates array is not set in any of the meshes.
8798 * \throw If the nodal connectivity of cells is not defined in any of the meshes.
8799 * \throw If any of the meshes is not a 2D mesh in 2D space.
8801 * \sa conformize2D, mergeNodes
8803 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8804 double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8807 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
8808 m1->checkFullyDefined();
8809 m2->checkFullyDefined();
8810 if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8811 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!");
8813 // Step 1: compute all edge intersections (new nodes)
8814 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8815 MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
8816 DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8817 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
8818 IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
8819 m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8820 addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
8821 revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8822 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8823 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8825 // Step 2: re-order newly created nodes according to the ordering found in m2
8826 std::vector< std::vector<int> > intersectEdge2;
8827 BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8828 subDiv2.clear(); dd5=0; dd6=0;
8831 std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8832 std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8833 BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8834 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8836 // Step 4: Prepare final result:
8837 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
8838 addCooDa->alloc((int)(addCoo.size())/2,2);
8839 std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8840 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
8841 addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8842 std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8843 std::vector<const DataArrayDouble *> coordss(4);
8844 coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8845 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
8846 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
8847 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8848 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8849 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8850 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8851 ret->setConnectivity(conn,connI,true);
8852 ret->setCoords(coo);
8853 cellNb1=c1.retn(); cellNb2=c2.retn();
8859 bool IsColinearOfACellOf(const std::vector< std::vector<int> >& intersectEdge1, const std::vector<int>& candidates, int start, int stop, int& retVal)
8861 if(candidates.empty())
8863 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
8865 const std::vector<int>& pool(intersectEdge1[*it]);
8866 int tmp[2]; tmp[0]=start; tmp[1]=stop;
8867 if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
8872 tmp[0]=stop; tmp[1]=start;
8873 if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
8882 MEDCouplingUMesh *BuildMesh1DCutFrom(const MEDCouplingUMesh *mesh1D, const std::vector< std::vector<int> >& intersectEdge2, const DataArrayDouble *coords1, const std::vector<double>& addCoo, const std::map<int,int>& mergedNodes, const std::vector< std::vector<int> >& colinear2, const std::vector< std::vector<int> >& intersectEdge1,
8883 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInRetColinear, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInMesh1DForIdsInRetColinear)
8885 idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1);
8886 idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1);
8887 int nCells(mesh1D->getNumberOfCells());
8888 if(nCells!=(int)intersectEdge2.size())
8889 throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
8890 const DataArrayDouble *coo2(mesh1D->getCoords());
8891 const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
8892 const double *coo2Ptr(coo2->begin());
8893 int offset1(coords1->getNumberOfTuples());
8894 int offset2(offset1+coo2->getNumberOfTuples());
8895 int offset3(offset2+addCoo.size()/2);
8896 std::vector<double> addCooQuad;
8897 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
8898 int tmp[4],cicnt(0),kk(0);
8899 for(int i=0;i<nCells;i++)
8901 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
8902 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
8903 const std::vector<int>& subEdges(intersectEdge2[i]);
8904 int nbSubEdge(subEdges.size()/2);
8905 for(int j=0;j<nbSubEdge;j++,kk++)
8907 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> n1(MEDCouplingUMeshBuildQPNode(subEdges[2*j],coords1->begin(),offset1,coo2Ptr,offset2,addCoo)),n2(MEDCouplingUMeshBuildQPNode(subEdges[2*j+1],coords1->begin(),offset1,coo2Ptr,offset2,addCoo));
8908 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
8909 INTERP_KERNEL::Edge *e2Ptr(e2);
8910 std::map<int,int>::const_iterator itm;
8911 if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
8913 tmp[0]=INTERP_KERNEL::NORM_SEG3;
8914 itm=mergedNodes.find(subEdges[2*j]);
8915 tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
8916 itm=mergedNodes.find(subEdges[2*j+1]);
8917 tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
8918 tmp[3]=offset3+(int)addCooQuad.size()/2;
8920 e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2);
8922 cOut->insertAtTheEnd(tmp,tmp+4);
8923 ciOut->pushBackSilent(cicnt);
8927 tmp[0]=INTERP_KERNEL::NORM_SEG2;
8928 itm=mergedNodes.find(subEdges[2*j]);
8929 tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
8930 itm=mergedNodes.find(subEdges[2*j+1]);
8931 tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
8933 cOut->insertAtTheEnd(tmp,tmp+3);
8934 ciOut->pushBackSilent(cicnt);
8937 if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00))
8939 idsInRetColinear->pushBackSilent(kk);
8940 idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00);
8945 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
8946 ret->setConnectivity(cOut,ciOut,true);
8947 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr3(DataArrayDouble::New());
8948 arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
8949 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
8950 std::vector<const DataArrayDouble *> coordss(4);
8951 coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
8952 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
8953 ret->setCoords(arr);
8957 MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
8959 std::vector<int> allEdges;
8960 for(const int *it2(descBg);it2!=descEnd;it2++)
8962 const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
8964 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
8966 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
8968 std::size_t nb(allEdges.size());
8970 throw INTERP_KERNEL::Exception("BuildRefined2DCell : internal error 1 !");
8971 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
8972 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
8973 ret->setCoords(coords);
8974 ret->allocateCells(1);
8975 std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
8976 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
8977 connOut[kk]=allEdges[2*kk];
8978 ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]);
8982 void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector<int>& conn, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edges)
8985 for(std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >::const_iterator it=edges.begin();it!=edges.end();it++)
8987 const INTERP_KERNEL::Edge *ee(*it);
8988 if(dynamic_cast<const INTERP_KERNEL::EdgeArcCircle *>(ee))
8992 mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]);
8995 const double *coo(mesh2D->getCoords()->begin());
8996 std::size_t sz(conn.size());
8997 std::vector<double> addCoo;
8998 std::vector<int> conn2(conn);
8999 int offset(mesh2D->getNumberOfNodes());
9000 for(std::size_t i=0;i<sz;i++)
9003 edges[(i+1)%sz]->getMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);
9004 addCoo.insert(addCoo.end(),tmp,tmp+2);
9005 conn2.push_back(offset+(int)i);
9007 mesh2D->getCoords()->rearrange(1);
9008 mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size());
9009 mesh2D->getCoords()->rearrange(2);
9010 mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]);
9015 * \b WARNING edges in out1 coming from \a splitMesh1D are \b NOT oriented because only used for equation of curve.
9017 void BuildMesh2DCutInternal2(const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& edge1Bis, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edge1BisPtr,
9018 std::vector< std::vector<int> >& out0, std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& out1)
9020 std::size_t nb(edge1Bis.size()/2);
9021 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9022 int iEnd(splitMesh1D->getNumberOfCells());
9024 throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal2 : internal error ! input 1D mesh must have at least one cell !");
9026 const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9027 for(ii=0;ii<nb && edge1Bis[2*ii]!=cSplitPtr[ciSplitPtr[0]+1];ii++);
9028 for(jj=ii;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd-1]+2];jj++);
9031 {//the edges splitMesh1D[iStart:iEnd] does not fully cut the current 2D cell -> single output cell
9032 out0.resize(1); out1.resize(1);
9033 std::vector<int>& connOut(out0[0]);
9034 connOut.resize(nbOfEdgesOf2DCellSplit);
9035 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr(out1[0]);
9036 edgesPtr.resize(nbOfEdgesOf2DCellSplit);
9037 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9039 connOut[kk]=edge1Bis[2*kk];
9040 edgesPtr[kk]=edge1BisPtr[2*kk];
9045 // [i,iEnd[ contains the
9046 out0.resize(2); out1.resize(2);
9047 std::vector<int>& connOutLeft(out0[0]);
9048 std::vector<int>& connOutRight(out0[1]);//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1]
9049 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eleft(out1[0]);
9050 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eright(out1[1]);
9051 for(std::size_t k=ii;k<jj+1;k++)
9052 { connOutLeft.push_back(edge1Bis[2*k+1]); eleft.push_back(edge1BisPtr[2*k+1]); }
9053 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > ees(iEnd);
9054 for(int ik=iEnd-1;ik>=0;ik--)
9056 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9057 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9060 for(int ik=iEnd-1;ik>=0;ik--)
9061 connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]);
9062 for(std::size_t k=jj+1;k<nbOfEdgesOf2DCellSplit+ii;k++)
9063 { connOutRight.push_back(edge1Bis[2*k+1]); eright.push_back(edge1BisPtr[2*k+1]); }
9064 eleft.insert(eleft.end(),ees.begin(),ees.end());
9065 for(int ik=0;ik<iEnd;ik++)
9066 connOutRight.push_back(cSplitPtr[ciSplitPtr[ik]+2]);
9067 eright.insert(eright.end(),ees.rbegin(),ees.rend());
9079 CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9081 std::vector<int> _edges;
9082 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > _edges_ptr;
9085 CellInfo::CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr)
9087 std::size_t nbe(edges.size());
9088 std::vector<int> edges2(2*nbe); std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edgesPtr2(2*nbe);
9089 for(std::size_t i=0;i<nbe;i++)
9091 edges2[2*i]=edges[i]; edges2[2*i+1]=edges[(i+1)%nbe];
9092 edgesPtr2[2*i]=edgesPtr[i]; edgesPtr2[2*i+1]=edgesPtr[i];
9094 _edges.resize(4*nbe); _edges_ptr.resize(4*nbe);
9095 std::copy(edges2.begin(),edges2.end(),_edges.begin()); std::copy(edges2.begin(),edges2.end(),_edges.begin()+2*nbe);
9096 std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()); std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()+2*nbe);
9102 EdgeInfo(int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh):_istart(istart),_iend(iend),_mesh(mesh),_left(-7),_right(-7) { }
9103 EdgeInfo(int istart, int iend, int pos, const MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge>& edge):_istart(istart),_iend(iend),_edge(edge),_left(pos),_right(pos+1) { }
9104 bool isInMyRange(int pos) const { return pos>=_istart && pos<_iend; }
9105 void somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9106 void feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const;
9110 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _mesh;
9111 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> _edge;
9116 void EdgeInfo::somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9118 const MEDCouplingUMesh *mesh(_mesh);
9124 { _left++; _right++; return ; }
9127 bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9128 if((isLeft && isRight) || (!isLeft && !isRight))
9129 throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 1 !");
9140 bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9141 if((isLeft && isRight) || (!isLeft && !isRight))
9142 throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 2 !");
9157 void EdgeInfo::feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const
9159 const MEDCouplingUMesh *mesh(_mesh);
9162 neighbors[0]=offset+_left; neighbors[1]=offset+_right;
9165 {// not fully splitting cell case
9166 if(mesh2D->getNumberOfCells()==1)
9167 {//little optimization. 1 cell no need to find in which cell mesh is !
9168 neighbors[0]=offset; neighbors[1]=offset;
9173 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9174 int cellId(mesh2D->getCellContainingPoint(barys->begin(),eps));
9176 throw INTERP_KERNEL::Exception("EdgeInfo::feedEdgeInfoAt : internal error !");
9177 neighbors[0]=offset+cellId; neighbors[1]=offset+cellId;
9182 class VectorOfCellInfo
9185 VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9186 std::size_t size() const { return _pool.size(); }
9187 int getPositionOf(double eps, const MEDCouplingUMesh *mesh) const;
9188 void setMeshAt(int pos, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh, int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh1DInCase, const std::vector< std::vector<int> >& edges, const std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& edgePtrs);
9189 const std::vector<int>& getConnOf(int pos) const { return get(pos)._edges; }
9190 const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& getEdgePtrOf(int pos) const { return get(pos)._edges_ptr; }
9191 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> getZeMesh() const { return _ze_mesh; }
9192 void feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const;
9194 int getZePosOfEdgeGivenItsGlobalId(int pos) const;
9195 void updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9196 const CellInfo& get(int pos) const;
9197 CellInfo& get(int pos);
9199 std::vector<CellInfo> _pool;
9200 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _ze_mesh;
9201 std::vector<EdgeInfo> _edge_info;
9204 VectorOfCellInfo::VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr):_pool(1)
9206 _pool[0]._edges=edges;
9207 _pool[0]._edges_ptr=edgesPtr;
9210 int VectorOfCellInfo::getPositionOf(double eps, const MEDCouplingUMesh *mesh) const
9213 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : empty !");
9216 const MEDCouplingUMesh *zeMesh(_ze_mesh);
9218 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : null aggregated mesh !");
9219 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9220 return zeMesh->getCellContainingPoint(barys->begin(),eps);
9223 void VectorOfCellInfo::setMeshAt(int pos, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh, int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh1DInCase, const std::vector< std::vector<int> >& edges, const std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& edgePtrs)
9225 get(pos);//to check pos
9226 bool isFast(pos==0 && _pool.size()==1);
9227 std::size_t sz(edges.size());
9228 // dealing with edges
9230 _edge_info.push_back(EdgeInfo(istart,iend,mesh1DInCase));
9232 _edge_info.push_back(EdgeInfo(istart,iend,pos,edgePtrs[0].back()));
9234 std::vector<CellInfo> pool(_pool.size()-1+sz);
9235 for(int i=0;i<pos;i++)
9237 for(std::size_t j=0;j<sz;j++)
9238 pool[pos+j]=CellInfo(edges[j],edgePtrs[j]);
9239 for(int i=pos+1;i<(int)_pool.size();i++)
9240 pool[pos+sz-1]=_pool[i];
9244 updateEdgeInfo(pos,edgePtrs[0],edgePtrs[1]);
9252 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > ms;
9255 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(0,pos,true)));
9259 if(pos<_ze_mesh->getNumberOfCells()-1)
9261 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(pos+1,_ze_mesh->getNumberOfCells(),true)));
9264 std::vector< const MEDCouplingUMesh *> ms2(ms.size());
9265 for(std::size_t j=0;j<ms2.size();j++)
9267 _ze_mesh=MEDCouplingUMesh::MergeUMeshesOnSameCoords(ms2);
9270 void VectorOfCellInfo::feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const
9272 _edge_info[getZePosOfEdgeGivenItsGlobalId(pos)].feedEdgeInfoAt(eps,_ze_mesh,offset,neighbors);
9275 int VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId(int pos) const
9278 throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id ! Must be >=0 !");
9280 for(std::vector<EdgeInfo>::const_iterator it=_edge_info.begin();it!=_edge_info.end();it++,ret++)
9282 if((*it).isInMyRange(pos))
9285 throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id !");
9288 void VectorOfCellInfo::updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9290 get(pos);//to check;
9291 if(_edge_info.empty())
9293 std::size_t sz(_edge_info.size()-1);
9294 for(std::size_t i=0;i<sz;i++)
9295 _edge_info[i].somethingHappendAt(pos,newLeft,newRight);
9298 const CellInfo& VectorOfCellInfo::get(int pos) const
9300 if(pos<0 || pos>=(int)_pool.size())
9301 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get const : invalid pos !");
9305 CellInfo& VectorOfCellInfo::get(int pos)
9307 if(pos<0 || pos>=(int)_pool.size())
9308 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get : invalid pos !");
9312 MEDCouplingUMesh *BuildMesh2DCutInternal(double eps, const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& allEdges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& allEdgesPtr, int offset,
9313 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9315 int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells());
9316 if(nbCellsInSplitMesh1D==0)
9317 throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal : internal error ! input 1D mesh must have at least one cell !");
9318 const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9319 std::size_t nb(allEdges.size()),jj;
9321 throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !");
9322 std::vector<int> edge1Bis(nb*2);
9323 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edge1BisPtr(nb*2);
9324 std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin());
9325 std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb);
9326 std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin());
9327 std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb);
9329 idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(nbCellsInSplitMesh1D*2); idsLeftRight->fillWithValue(-2); idsLeftRight->rearrange(2);
9330 int *idsLeftRightPtr(idsLeftRight->getPointer());
9331 VectorOfCellInfo pool(edge1Bis,edge1BisPtr);
9332 for(int iStart=0;iStart<nbCellsInSplitMesh1D;)
9333 {// split [0:nbCellsInSplitMesh1D) in contiguous parts [iStart:iEnd)
9335 for(;iEnd<nbCellsInSplitMesh1D;)
9337 for(jj=0;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd]+2];jj++);
9343 if(iEnd<nbCellsInSplitMesh1D)
9346 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfSplitMesh1D(static_cast<MEDCouplingUMesh *>(splitMesh1D->buildPartOfMySelf2(iStart,iEnd,1,true)));
9347 int pos(pool.getPositionOf(eps,partOfSplitMesh1D));
9349 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>retTmp(MEDCouplingUMesh::New("",2));
9350 retTmp->setCoords(splitMesh1D->getCoords());
9351 retTmp->allocateCells();
9353 std::vector< std::vector<int> > out0;
9354 std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > > out1;
9356 BuildMesh2DCutInternal2(partOfSplitMesh1D,pool.getConnOf(pos),pool.getEdgePtrOf(pos),out0,out1);
9357 for(std::size_t cnt=0;cnt<out0.size();cnt++)
9358 AddCellInMesh2D(retTmp,out0[cnt],out1[cnt]);
9359 pool.setMeshAt(pos,retTmp,iStart,iEnd,partOfSplitMesh1D,out0,out1);
9363 for(int mm=0;mm<nbCellsInSplitMesh1D;mm++)
9364 pool.feedEdgeInfoAt(eps,mm,offset,idsLeftRightPtr+2*mm);
9365 return pool.getZeMesh().retn();
9368 MEDCouplingUMesh *BuildMesh2DCutFrom(double eps, int cellIdInMesh2D, const MEDCouplingUMesh *mesh2DDesc, const MEDCouplingUMesh *splitMesh1D,
9369 const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1, int offset,
9370 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9372 const int *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin());
9374 std::vector<int> allEdges;
9375 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > allEdgesPtr;
9376 for(const int *it(descBg);it!=descEnd;it++)
9378 int edgeId(std::abs(*it)-1);
9379 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9380 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m));
9381 const std::vector<int>& edge1(intersectEdge1[edgeId]);
9383 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9385 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9386 std::size_t sz(edge1.size());
9387 for(std::size_t cnt=0;cnt<sz;cnt++)
9388 allEdgesPtr.push_back(ee);
9391 return BuildMesh2DCutInternal(eps,splitMesh1D,allEdges,allEdgesPtr,offset,idsLeftRight);
9397 * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
9398 * Thus the final result contains the aggregation of nodes of \a mesh2D, then nodes of \a mesh1D, then new nodes that are the result of the intersection
9399 * and finaly, in case of quadratic polygon the centers of edges new nodes.
9400 * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
9402 * \param [in] mesh2D - the 2D mesh (spacedim=meshdim=2) to be intersected using \a mesh1D tool. The mesh must be so that each point in the space covered by \a mesh2D
9403 * must be covered exactly by one entity, \b no \b more. If it is not the case, some tools are available to heal the mesh (conformize2D, mergeNodes)
9404 * \param [in] mesh1D - the 1D mesh (spacedim=2 meshdim=1) the is the tool that will be used to intersect \a mesh2D. \a mesh1D must be ordered consecutively. If it is not the case
9405 * you can invoke orderConsecutiveCells1D on \a mesh1D.
9406 * \param [in] eps - precision used to perform intersections and localization operations.
9407 * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
9408 * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
9409 * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
9410 * So this array has a number of tuples equal to the number of cells of \a splitMesh2D and a number of component equal to 1.
9411 * \param [out] cellIdInMesh1D - the array of pair that gives for each cell id \a i in \a splitMesh1D the cell in \a splitMesh2D on the left for the 1st component
9412 * and the cell in \a splitMesh2D on the right for the 2nt component. -1 means no cell.
9413 * So this array has a number of tuples equal to the number of cells of \a splitMesh1D and a number of components equal to 2.
9415 * \sa Intersect2DMeshes, orderConsecutiveCells1D, conformize2D, mergeNodes
9417 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
9419 if(!mesh2D || !mesh1D)
9420 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
9421 mesh2D->checkFullyDefined();
9422 mesh1D->checkFullyDefined();
9423 const std::vector<std::string>& compNames(mesh2D->getCoords()->getInfoOnComponents());
9424 if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
9425 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
9426 // Step 1: compute all edge intersections (new nodes)
9427 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9428 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
9429 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9430 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9432 // Build desc connectivity
9433 DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
9434 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9435 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
9436 std::map<int,int> mergedNodes;
9437 Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes);
9438 // use mergeNodes to fix intersectEdge1
9439 for(std::vector< std::vector<int> >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++)
9441 std::size_t n((*it0).size()/2);
9442 int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]);
9443 std::map<int,int>::const_iterator it1;
9444 it1=mergedNodes.find(eltStart);
9445 if(it1!=mergedNodes.end())
9446 (*it0)[0]=(*it1).second;
9447 it1=mergedNodes.find(eltEnd);
9448 if(it1!=mergedNodes.end())
9449 (*it0)[2*n-1]=(*it1).second;
9452 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9453 addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9454 // Step 2: re-order newly created nodes according to the ordering found in m2
9455 std::vector< std::vector<int> > intersectEdge2;
9456 BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
9458 // Step 3: compute splitMesh1D
9459 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear;
9460 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2(DataArrayInt::New()); ret2->alloc(0,1);
9461 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1,
9462 idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear));
9463 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(-1); ret3->rearrange(2);
9464 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells()));
9465 // deal with cells in mesh2D that are not cut but only some of their edges are
9466 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCpy());
9467 idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1);
9468 idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique();
9469 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s;//ids in mesh2D that are impacted by the fact that some edges of \a mesh1D are part of the edges of those cells
9470 if(!idsInDesc2DToBeRefined->empty())
9472 DataArrayInt *out0(0),*outi0(0);
9473 MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
9474 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> outi0s(outi0);
9476 out0s=out0s->buildUnique();
9480 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1NonCol(static_cast<MEDCouplingUMesh *>(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end())));
9481 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> baryRet1(ret1NonCol->getBarycenterAndOwner());
9482 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elts,eltsIndex;
9483 mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
9484 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex2(eltsIndex->deltaShiftIndex());
9485 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex3(eltsIndex2->getIdsEqual(1));
9486 if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells())
9487 throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !");
9488 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToBeModified(elts->buildUnique());
9489 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells()));
9490 if((DataArrayInt *)out0s)
9491 untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one
9492 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > outMesh2DSplit;
9493 // OK all is ready to insert in ret2 mesh
9494 if(!untouchedCells->empty())
9495 {// the most easy part, cells in mesh2D not impacted at all
9496 outMesh2DSplit.push_back(static_cast<MEDCouplingUMesh *>(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end())));
9497 outMesh2DSplit.back()->setCoords(ret1->getCoords());
9498 ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end());
9500 if((DataArrayInt *)out0s)
9501 {// here dealing with cells in out0s but not in cellsToBeModified
9502 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fewModifiedCells(out0s->buildSubstraction(cellsToBeModified));
9503 const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin());
9504 for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++)
9506 outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1));
9508 int offset(ret2->getNumberOfTuples());
9509 ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end());
9510 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1);
9511 partOfRet3->fillWithValue(-1); partOfRet3->rearrange(2);
9512 int kk(0),*ret3ptr(partOfRet3->getPointer());
9513 for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++)
9515 int faceId(std::abs(*it)-1);
9516 for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++)
9518 int tmp(fewModifiedCells->locateValue(*it2));
9521 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9522 ret3ptr[2*kk]=tmp+offset;
9523 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9524 ret3ptr[2*kk+1]=tmp+offset;
9527 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : internal error 1 !");
9530 ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true);
9532 for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++)
9534 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell(elts->getIdsEqual(*it));
9535 idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end());
9536 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end()));
9537 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfMesh1CuttingCur2DCell(static_cast<MEDCouplingUMesh *>(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end())));
9538 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3;
9539 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> splitOfOneCell(BuildMesh2DCutFrom(eps,*it,m1Desc,partOfMesh1CuttingCur2DCell,dd1->begin()+dd2->getIJ(*it,0),dd1->begin()+dd2->getIJ((*it)+1,0),intersectEdge1,ret2->getNumberOfTuples(),partOfRet3));
9540 ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true);
9541 outMesh2DSplit.push_back(splitOfOneCell);
9542 for(int i=0;i<splitOfOneCell->getNumberOfCells();i++)
9543 ret2->pushBackSilent(*it);
9546 std::size_t nbOfMeshes(outMesh2DSplit.size());
9547 std::vector<const MEDCouplingUMesh *> tmp(nbOfMeshes);
9548 for(std::size_t i=0;i<nbOfMeshes;i++)
9549 tmp[i]=outMesh2DSplit[i];
9551 ret1->getCoords()->setInfoOnComponents(compNames);
9553 splitMesh1D=ret1.retn();
9554 splitMesh2D=MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp);
9555 cellIdInMesh2D=ret2.retn();
9556 cellIdInMesh1D=ret3.retn();
9560 * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
9561 * (newly created) nodes corresponding to the edge intersections.
9563 * @param[out] cr, crI connectivity of the resulting mesh
9564 * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
9565 * TODO: describe input parameters
9567 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
9568 const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
9569 const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
9570 const std::vector<double>& addCoords,
9571 std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
9573 static const int SPACEDIM=2;
9574 const double *coo1(m1->getCoords()->getConstPointer());
9575 const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer());
9576 int offset1(m1->getNumberOfNodes());
9577 const double *coo2(m2->getCoords()->getConstPointer());
9578 const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer());
9579 int offset2(offset1+m2->getNumberOfNodes());
9580 int offset3(offset2+((int)addCoords.size())/2);
9581 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
9582 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9583 // Here a BBTree on 2D-cells, not on segments:
9584 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
9585 int ncell1(m1->getNumberOfCells());
9587 for(int i=0;i<ncell1;i++)
9589 std::vector<int> candidates2;
9590 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9591 std::map<INTERP_KERNEL::Node *,int> mapp;
9592 std::map<int,INTERP_KERNEL::Node *> mappRev;
9593 INTERP_KERNEL::QuadraticPolygon pol1;
9594 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
9595 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
9596 // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
9597 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
9598 // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
9599 pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
9600 desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
9602 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
9603 std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
9604 INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
9605 for(it1.first();!it1.finished();it1.next())
9606 edges1.insert(it1.current()->getPtr());
9608 std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
9609 std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
9611 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9613 INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
9614 const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
9615 // Complete mapping with elements coming from the current cell it2 in mesh2:
9616 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
9617 // pol2 is the new QP in the final merged result.
9618 pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
9619 pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
9622 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9624 INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
9625 pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
9626 //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
9627 pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9629 // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
9630 // by m2 but that we still want to keep in the final result.
9635 INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9637 catch(INTERP_KERNEL::Exception& e)
9639 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();
9640 throw INTERP_KERNEL::Exception(oss.str().c_str());
9643 for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
9644 (*it).second->decrRef();
9649 * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
9650 * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
9651 * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
9652 * The caller is to deal with the resulting DataArrayInt.
9653 * \throw If the coordinate array is not set.
9654 * \throw If the nodal connectivity of the cells is not defined.
9655 * \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
9656 * \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
9658 * \sa DataArrayInt::sortEachPairToMakeALinkedList
9660 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
9662 checkFullyDefined();
9663 if(getMeshDimension()!=1)
9664 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
9666 // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
9667 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
9668 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
9669 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
9670 const int *d(_d->getConstPointer()), *dI(_dI->getConstPointer());
9671 const int *rD(_rD->getConstPointer()), *rDI(_rDI->getConstPointer());
9672 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
9673 const int * dsi(_dsi->getConstPointer());
9674 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dsii = _dsi->getIdsNotInRange(0,3);
9676 if (dsii->getNumberOfTuples())
9677 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
9679 int nc(getNumberOfCells());
9680 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> result(DataArrayInt::New());
9681 result->alloc(nc,1);
9683 // set of edges not used so far
9684 std::set<int> edgeSet;
9685 for (int i=0; i<nc; edgeSet.insert(i), i++);
9689 // while we have points with only one neighbor segments
9692 std::list<int> linePiece;
9693 // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
9694 for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
9696 // Fill the list forward (resp. backward) from the start segment:
9697 int activeSeg = startSeg;
9698 int prevPointId = -20;
9700 while (!edgeSet.empty())
9702 if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
9705 linePiece.push_back(activeSeg);
9707 linePiece.push_front(activeSeg);
9708 edgeSet.erase(activeSeg);
9711 int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
9712 ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
9713 if (dsi[ptId] == 1) // hitting the end of the line
9716 int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
9717 activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
9720 // Done, save final piece into DA:
9721 std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
9722 newIdx += linePiece.size();
9724 // identify next valid start segment (one which is not consumed)
9725 if(!edgeSet.empty())
9726 startSeg = *(edgeSet.begin());
9728 while (!edgeSet.empty());
9729 return result.retn();
9734 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
9736 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> nTmp(n); nTmp->incrRef();
9737 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>::const_iterator it(m.find(nTmp));
9739 throw INTERP_KERNEL::Exception("Internal error in remapping !");
9740 int v((*it).second);
9741 if(v==forbVal0 || v==forbVal1)
9743 if(std::find(isect.begin(),isect.end(),v)==isect.end())
9747 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
9752 bool presenceOfOn(false);
9753 for(int i=0;i<sz;i++)
9755 INTERP_KERNEL::ElementaryEdge *e(c[i]);
9756 if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
9758 IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
9759 IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
9761 return presenceOfOn;
9767 * This method split some of edges of 2D cells in \a this. The edges to be split are specified in \a subNodesInSeg and in \a subNodesInSegI using index storage mode.
9768 * To do the work this method can optionally needs information about middle of subedges for quadratic cases if a minimal creation of new nodes is wanted.
9769 * So this method try to reduce at most the number of new nodes. The only case that can lead this method to add nodes if a SEG3 is split without information of middle.
9770 * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to avoid to have a non conform mesh.
9772 * \return int - the number of new nodes created (in most of cases 0).
9774 * \throw If \a this is not coherent.
9775 * \throw If \a this has not spaceDim equal to 2.
9776 * \throw If \a this has not meshDim equal to 2.
9777 * \throw If some subcells needed to be split are orphan.
9778 * \sa MEDCouplingUMesh::conformize2D
9780 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
9782 if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
9783 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
9784 desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
9785 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
9786 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
9787 if(midOpt==0 && midOptI==0)
9789 split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
9792 else if(midOpt!=0 && midOptI!=0)
9793 return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
9795 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
9799 * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
9800 * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
9801 * This method performs a conformization of \b this. So if a edge in \a this can be split into entire edges in \a this this method
9802 * will suppress such edges to use sub edges in \a this. So this method does not add nodes in \a this if merged edges are both linear (INTERP_KERNEL::NORM_SEG2).
9803 * In the other cases new nodes can be created. If any are created, they will be appended at the end of the coordinates object before the invokation of this method.
9805 * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
9806 * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
9808 * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
9809 * This method expects that all nodes in \a this are not closer than \a eps.
9810 * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
9812 * \param [in] eps the relative error to detect merged edges.
9813 * \return DataArrayInt * - The list of cellIds in \a this that have been subdivided. If empty, nothing changed in \a this (as if it were a const method). The array is a newly allocated array
9814 * that the user is expected to deal with.
9816 * \throw If \a this is not coherent.
9817 * \throw If \a this has not spaceDim equal to 2.
9818 * \throw If \a this has not meshDim equal to 2.
9819 * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
9821 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
9823 static const int SPACEDIM=2;
9825 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
9826 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
9827 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
9828 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
9829 const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
9830 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
9831 const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
9832 int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
9833 std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
9834 std::vector<double> addCoo;
9835 BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
9836 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9837 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9838 for(int i=0;i<nDescCell;i++)
9840 std::vector<int> candidates;
9841 myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
9842 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
9845 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9846 INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
9847 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
9848 INTERP_KERNEL::MergePoints merge;
9849 INTERP_KERNEL::QuadraticPolygon c1,c2;
9850 e1->intersectWith(e2,merge,c1,c2);
9851 e1->decrRef(); e2->decrRef();
9852 if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
9853 overlapEdge[i].push_back(*it);
9854 if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
9855 overlapEdge[*it].push_back(i);
9858 // splitting done. sort intersect point in intersectEdge.
9859 std::vector< std::vector<int> > middle(nDescCell);
9860 int nbOf2DCellsToBeSplit(0);
9861 bool middleNeedsToBeUsed(false);
9862 std::vector<bool> cells2DToTreat(nDescCell,false);
9863 for(int i=0;i<nDescCell;i++)
9865 std::vector<int>& isect(intersectEdge[i]);
9866 int sz((int)isect.size());
9869 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9870 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
9871 e->sortSubNodesAbs(coords,isect);
9876 int idx0(rdi[i]),idx1(rdi[i+1]);
9878 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
9879 if(!cells2DToTreat[rd[idx0]])
9881 cells2DToTreat[rd[idx0]]=true;
9882 nbOf2DCellsToBeSplit++;
9884 // try to reuse at most eventual 'middle' of SEG3
9885 std::vector<int>& mid(middle[i]);
9886 mid.resize(sz+1,-1);
9887 if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
9889 middleNeedsToBeUsed=true;
9890 const std::vector<int>& candidates(overlapEdge[i]);
9891 std::vector<int> trueCandidates;
9892 for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
9893 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
9894 trueCandidates.push_back(*itc);
9895 int stNode(c[ci[i]+1]),endNode(isect[0]);
9896 for(int j=0;j<sz+1;j++)
9898 for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
9900 int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
9901 if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
9902 { mid[j]=*itc; break; }
9905 endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
9910 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
9911 if(nbOf2DCellsToBeSplit==0)
9914 int *retPtr(ret->getPointer());
9915 for(int i=0;i<nCell;i++)
9916 if(cells2DToTreat[i])
9919 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
9920 DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
9921 MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
9922 DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
9923 if(middleNeedsToBeUsed)
9924 { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
9925 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
9926 int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
9927 setCoords(modif->getCoords());//if nbOfNodesCreated==0 modif and this have the same coordinates pointer so this line has no effect. But for quadratic cases this line is important.
9928 setPartOfMySelf(ret->begin(),ret->end(),*modif);
9930 bool areNodesMerged; int newNbOfNodes;
9931 if(nbOfNodesCreated!=0)
9932 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
9938 * This non const method works on 2D mesh. This method scans every cell in \a this and look if each edge constituting this cell is not mergeable with neighbors edges of that cell.
9939 * If yes, the cell is "repaired" to minimize at most its number of edges. So this method do not change the overall shape of cells in \a this (with eps precision).
9940 * This method do not take care of shared edges between cells, so this method can lead to a non conform mesh (\a this). If a conform mesh is required you're expected
9941 * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
9942 * This method works on any 2D geometric types of cell (even static one). If a cell is touched its type becomes dynamic automaticaly. For 2D "repaired" quadratic cells
9943 * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
9945 * If the returned array is empty it means that nothing has changed in \a this (as if it were a const method). If the array is not empty the connectivity of \a this is modified
9946 * using new instance, idem for coordinates.
9948 * If \a this is constituted by only linear 2D cells, this method is close to the computation of the convex hull of each cells in \a this.
9950 * \return DataArrayInt * - The list of cellIds in \a this that have at least one edge colinearized.
9952 * \throw If \a this is not coherent.
9953 * \throw If \a this has not spaceDim equal to 2.
9954 * \throw If \a this has not meshDim equal to 2.
9956 * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
9958 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
9960 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
9962 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
9963 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
9964 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9965 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9966 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
9967 const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
9968 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
9969 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
9970 const double *coords(_coords->begin());
9971 int *newciptr(newci->getPointer());
9972 for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
9974 if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
9975 ret->pushBackSilent(i);
9976 newciptr[1]=newc->getNumberOfTuples();
9981 if(!appendedCoords->empty())
9983 appendedCoords->rearrange(2);
9984 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
9986 setCoords(newCoords);
9989 setConnectivity(newc,newci,true);
9994 * \param [out] intersectEdge1 - for each cell in \a m1Desc returns the result of the split. The result is given using pair of int given resp start and stop.
9995 * So for all edge \a i in \a m1Desc \a intersectEdge1[i] is of length 2*n where n is the number of sub edges.
9996 * And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
9997 * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
9998 * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
9999 * \param [out] addCoo - nodes to be append at the end
10000 * \param [out] mergedNodes - gives all pair of nodes of \a m2Desc that have same location than some nodes in \a m1Desc. key is id in \a m2Desc offseted and value is id in \a m1Desc.
10002 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
10003 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2, std::vector<double>& addCoo, std::map<int,int>& mergedNodes)
10005 static const int SPACEDIM=2;
10006 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10007 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10008 const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer());
10009 // Build BB tree of all edges in the tool mesh (second mesh)
10010 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
10011 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10012 int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
10013 intersectEdge1.resize(nDescCell1);
10014 colinear2.resize(nDescCell2);
10015 subDiv2.resize(nDescCell2);
10016 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
10018 std::vector<int> candidates1(1);
10019 int offset1(m1Desc->getNumberOfNodes());
10020 int offset2(offset1+m2Desc->getNumberOfNodes());
10021 for(int i=0;i<nDescCell1;i++) // for all edges in the first mesh
10023 std::vector<int> candidates2; // edges of mesh2 candidate for intersection
10024 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10025 if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
10027 std::map<INTERP_KERNEL::Node *,int> map1,map2;
10028 // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
10029 INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
10031 INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
10032 // This following part is to avoid that some removed nodes (for example due to a merge between pol1 and pol2) are replaced by a newly created one
10033 // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
10034 std::set<INTERP_KERNEL::Node *> nodes;
10035 pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
10036 std::size_t szz(nodes.size());
10037 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
10038 std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
10039 for(std::size_t iii=0;iii<szz;iii++,itt++)
10040 { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
10041 // end of protection
10042 // Performs egde cutting:
10043 pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes);
10048 // Copy the edge (take only the two first points, ie discard quadratic point at this stage)
10049 intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i]+3);
10054 * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
10055 * It builds the descending connectivity of the two meshes, and then using a binary tree
10056 * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
10057 * Documentation about parameters colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
10059 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
10060 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
10061 MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
10062 std::vector<double>& addCoo,
10063 MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
10065 // Build desc connectivity
10066 desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
10067 desc2=DataArrayInt::New();
10068 descIndx2=DataArrayInt::New();
10069 revDesc2=DataArrayInt::New();
10070 revDescIndx2=DataArrayInt::New();
10071 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
10072 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
10073 m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
10074 m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
10075 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
10076 std::map<int,int> notUsedMap;
10077 Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap);
10078 m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
10079 m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
10083 * This method performs the 2nd step of Partition of 2D mesh.
10084 * This method has 4 inputs :
10085 * - a mesh 'm1' with meshDim==1 and a SpaceDim==2
10086 * - a mesh 'm2' with meshDim==1 and a SpaceDim==2
10087 * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
10088 * The aim of this method is to sort the splitting nodes, if any, and to put them in 'intersectEdge' output parameter based on edges of mesh 'm2'
10089 * Nodes end up lying consecutively on a cutted edge.
10090 * \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.
10091 * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
10092 * \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.
10093 * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
10094 * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
10096 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
10097 const std::vector<double>& addCoo,
10098 const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
10100 int offset1=m1->getNumberOfNodes();
10101 int ncell=m2->getNumberOfCells();
10102 const int *c=m2->getNodalConnectivity()->getConstPointer();
10103 const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
10104 const double *coo=m2->getCoords()->getConstPointer();
10105 const double *cooBis=m1->getCoords()->getConstPointer();
10106 int offset2=offset1+m2->getNumberOfNodes();
10107 intersectEdge.resize(ncell);
10108 for(int i=0;i<ncell;i++,cI++)
10110 const std::vector<int>& divs=subDiv[i];
10111 int nnode=cI[1]-cI[0]-1;
10112 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
10113 std::map<INTERP_KERNEL::Node *, int> mapp22;
10114 for(int j=0;j<nnode;j++)
10116 INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
10117 int nnid=c[(*cI)+j+1];
10118 mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
10119 mapp22[nn]=nnid+offset1;
10121 INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
10122 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
10123 ((*it).second.first)->decrRef();
10124 std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
10125 std::map<INTERP_KERNEL::Node *,int> mapp3;
10126 for(std::size_t j=0;j<divs.size();j++)
10129 INTERP_KERNEL::Node *tmp=0;
10131 tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
10132 else if(id<offset2)
10133 tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
10135 tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
10139 e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
10140 for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
10147 * 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).
10148 * 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
10149 * with a plane. The result will be put in 'cut3DSuf' out parameter.
10150 * \param [in] cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
10151 * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
10152 * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
10153 * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
10154 * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
10155 * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
10156 * \param [in] desc is the descending connectivity 3DSurf->3DCurve
10157 * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
10158 * \param [out] cut3DSuf input/output param.
10160 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
10161 const int *nodal3DCurve, const int *nodalIndx3DCurve,
10162 const int *desc, const int *descIndx,
10163 std::vector< std::pair<int,int> >& cut3DSurf)
10165 std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
10166 int nbOf3DSurfCell=(int)cut3DSurf.size();
10167 for(int i=0;i<nbOf3DSurfCell;i++)
10169 std::vector<int> res;
10170 int offset=descIndx[i];
10171 int nbOfSeg=descIndx[i+1]-offset;
10172 for(int j=0;j<nbOfSeg;j++)
10174 int edgeId=desc[offset+j];
10175 int status=cut3DCurve[edgeId];
10179 res.push_back(status);
10182 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
10183 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
10191 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10197 std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
10198 std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
10201 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10205 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
10210 {// case when plane is on a multi colinear edge of a polyhedron
10211 if((int)res.size()==2*nbOfSeg)
10213 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
10216 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
10223 * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
10224 * 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).
10225 * 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
10226 * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
10227 * \param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
10228 * \param desc is the descending connectivity 3D->3DSurf
10229 * \param descIndx is the descending connectivity index 3D->3DSurf
10231 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
10232 const int *desc, const int *descIndx,
10233 DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
10235 checkFullyDefined();
10236 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10237 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
10238 const int *nodal3D=_nodal_connec->getConstPointer();
10239 const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
10240 int nbOfCells=getNumberOfCells();
10241 for(int i=0;i<nbOfCells;i++)
10243 std::map<int, std::set<int> > m;
10244 int offset=descIndx[i];
10245 int nbOfFaces=descIndx[i+1]-offset;
10248 for(int j=0;j<nbOfFaces;j++)
10250 const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
10251 if(p.first!=-1 && p.second!=-1)
10255 start=p.first; end=p.second;
10256 m[p.first].insert(p.second);
10257 m[p.second].insert(p.first);
10261 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
10262 int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
10263 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
10264 INTERP_KERNEL::NormalizedCellType cmsId;
10265 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
10266 start=tmp[0]; end=tmp[nbOfNodesSon-1];
10267 for(unsigned k=0;k<nbOfNodesSon;k++)
10269 m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
10270 m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
10277 std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
10281 std::map<int, std::set<int> >::const_iterator it=m.find(start);
10282 const std::set<int>& s=(*it).second;
10283 std::set<int> s2; s2.insert(prev);
10285 std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
10288 int val=*s3.begin();
10289 conn.push_back(start);
10296 conn.push_back(end);
10299 nodalRes->insertAtTheEnd(conn.begin(),conn.end());
10300 nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
10301 cellIds->pushBackSilent(i);
10307 * 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
10308 * 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
10309 * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
10310 * 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
10311 * 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.
10313 * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
10315 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
10317 std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
10320 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
10321 if(cm.getDimension()==2)
10323 const int *node=nodalConnBg+1;
10324 int startNode=*node++;
10325 double refX=coords[2*startNode];
10326 for(;node!=nodalConnEnd;node++)
10328 if(coords[2*(*node)]<refX)
10331 refX=coords[2*startNode];
10334 std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
10338 double angle0=-M_PI/2;
10343 double angleNext=0.;
10344 while(nextNode!=startNode)
10348 for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
10350 if(*node!=tmpOut.back() && *node!=prevNode)
10352 tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
10353 double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
10358 res=angle0-angleM+2.*M_PI;
10367 if(nextNode!=startNode)
10369 angle0=angleNext-M_PI;
10372 prevNode=tmpOut.back();
10373 tmpOut.push_back(nextNode);
10376 std::vector<int> tmp3(2*(sz-1));
10377 std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
10378 std::copy(nodalConnBg+1,nodalConnEnd,it);
10379 if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
10381 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10384 if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
10386 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10391 nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
10392 nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
10397 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10400 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10404 * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
10405 * 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.
10407 * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
10408 * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
10409 * \param [in,out] arr array in which the remove operation will be done.
10410 * \param [in,out] arrIndx array in the remove operation will modify
10411 * \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])
10412 * \return true if \b arr and \b arrIndx have been modified, false if not.
10414 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
10416 if(!arrIndx || !arr)
10417 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
10418 if(offsetForRemoval<0)
10419 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
10420 std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
10421 int nbOfGrps=arrIndx->getNumberOfTuples()-1;
10422 int *arrIPtr=arrIndx->getPointer();
10424 int previousArrI=0;
10425 const int *arrPtr=arr->getConstPointer();
10426 std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
10427 for(int i=0;i<nbOfGrps;i++,arrIPtr++)
10429 if(*arrIPtr-previousArrI>offsetForRemoval)
10431 for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
10433 if(s.find(*work)==s.end())
10434 arrOut.push_back(*work);
10437 previousArrI=*arrIPtr;
10438 *arrIPtr=(int)arrOut.size();
10440 if(arr->getNumberOfTuples()==(int)arrOut.size())
10442 arr->alloc((int)arrOut.size(),1);
10443 std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
10448 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10449 * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
10450 * The selection of extraction is done standardly in new2old format.
10451 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10453 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10454 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10455 * \param [in] arrIn arr origin array from which the extraction will be done.
10456 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10457 * \param [out] arrOut the resulting array
10458 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10459 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
10461 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10462 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10464 if(!arrIn || !arrIndxIn)
10465 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
10466 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10467 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10468 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
10469 std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
10470 const int *arrInPtr=arrIn->getConstPointer();
10471 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10472 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10474 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10475 int maxSizeOfArr=arrIn->getNumberOfTuples();
10476 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10477 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10478 arrIo->alloc((int)(sz+1),1);
10479 const int *idsIt=idsOfSelectBg;
10480 int *work=arrIo->getPointer();
10483 for(std::size_t i=0;i<sz;i++,work++,idsIt++)
10485 if(*idsIt>=0 && *idsIt<nbOfGrps)
10486 lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
10489 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10490 throw INTERP_KERNEL::Exception(oss.str().c_str());
10496 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
10497 oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
10498 throw INTERP_KERNEL::Exception(oss.str().c_str());
10501 arro->alloc(lgth,1);
10502 work=arro->getPointer();
10503 idsIt=idsOfSelectBg;
10504 for(std::size_t i=0;i<sz;i++,idsIt++)
10506 if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
10507 work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
10510 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
10511 oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10512 throw INTERP_KERNEL::Exception(oss.str().c_str());
10515 arrOut=arro.retn();
10516 arrIndexOut=arrIo.retn();
10520 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10521 * This method returns the result of the extraction ( specified by a set of ids with a slice given by \a idsOfSelectStart, \a idsOfSelectStop and \a idsOfSelectStep ).
10522 * The selection of extraction is done standardly in new2old format.
10523 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10525 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10526 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10527 * \param [in] arrIn arr origin array from which the extraction will be done.
10528 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10529 * \param [out] arrOut the resulting array
10530 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10531 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
10533 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10534 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10536 if(!arrIn || !arrIndxIn)
10537 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
10538 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10539 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10540 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
10541 int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
10542 const int *arrInPtr=arrIn->getConstPointer();
10543 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10544 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10546 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10547 int maxSizeOfArr=arrIn->getNumberOfTuples();
10548 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10549 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10550 arrIo->alloc((int)(sz+1),1);
10551 int idsIt=idsOfSelectStart;
10552 int *work=arrIo->getPointer();
10555 for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
10557 if(idsIt>=0 && idsIt<nbOfGrps)
10558 lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
10561 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10562 throw INTERP_KERNEL::Exception(oss.str().c_str());
10568 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
10569 oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
10570 throw INTERP_KERNEL::Exception(oss.str().c_str());
10573 arro->alloc(lgth,1);
10574 work=arro->getPointer();
10575 idsIt=idsOfSelectStart;
10576 for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
10578 if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
10579 work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
10582 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
10583 oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10584 throw INTERP_KERNEL::Exception(oss.str().c_str());
10587 arrOut=arro.retn();
10588 arrIndexOut=arrIo.retn();
10592 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10593 * 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
10594 * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
10595 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
10597 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10598 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10599 * \param [in] arrIn arr origin array from which the extraction will be done.
10600 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10601 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
10602 * \param [in] srcArrIndex index array of \b srcArr
10603 * \param [out] arrOut the resulting array
10604 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10606 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
10608 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10609 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
10610 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10612 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10613 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
10614 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10615 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10616 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10617 std::vector<bool> v(nbOfTuples,true);
10619 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10620 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10621 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10623 if(*it>=0 && *it<nbOfTuples)
10626 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
10630 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
10631 throw INTERP_KERNEL::Exception(oss.str().c_str());
10634 srcArrIndexPtr=srcArrIndex->getConstPointer();
10635 arrIo->alloc(nbOfTuples+1,1);
10636 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
10637 const int *arrInPtr=arrIn->getConstPointer();
10638 const int *srcArrPtr=srcArr->getConstPointer();
10639 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
10640 int *arroPtr=arro->getPointer();
10641 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
10645 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
10646 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
10650 std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
10651 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
10652 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
10655 arrOut=arro.retn();
10656 arrIndexOut=arrIo.retn();
10660 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10661 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
10663 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10664 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10665 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
10666 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10667 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
10668 * \param [in] srcArrIndex index array of \b srcArr
10670 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
10672 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
10673 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
10675 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10676 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
10677 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10678 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10679 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10680 int *arrInOutPtr=arrInOut->getPointer();
10681 const int *srcArrPtr=srcArr->getConstPointer();
10682 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10684 if(*it>=0 && *it<nbOfTuples)
10686 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
10687 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
10690 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] !";
10691 throw INTERP_KERNEL::Exception(oss.str().c_str());
10696 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
10697 throw INTERP_KERNEL::Exception(oss.str().c_str());
10703 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
10704 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
10705 * 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]].
10706 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
10707 * A negative value in \b arrIn means that it is ignored.
10708 * 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.
10710 * \param [in] arrIn arr origin array from which the extraction will be done.
10711 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10712 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
10713 * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
10715 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
10717 int seed=0,nbOfDepthPeelingPerformed=0;
10718 return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
10722 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
10723 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
10724 * 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]].
10725 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
10726 * A negative value in \b arrIn means that it is ignored.
10727 * 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.
10728 * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
10729 * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
10730 * \param [in] arrIn arr origin array from which the extraction will be done.
10731 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10732 * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
10733 * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
10734 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
10735 * \sa MEDCouplingUMesh::partitionBySpreadZone
10737 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
10739 nbOfDepthPeelingPerformed=0;
10741 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
10742 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10745 DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
10749 std::vector<bool> fetched(nbOfTuples,false);
10750 return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
10753 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
10755 nbOfDepthPeelingPerformed=0;
10756 if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
10757 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
10758 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10759 std::vector<bool> fetched2(nbOfTuples,false);
10761 for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
10763 if(*seedElt>=0 && *seedElt<nbOfTuples)
10764 { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
10766 { 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()); }
10768 const int *arrInPtr=arrIn->getConstPointer();
10769 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10770 int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
10771 std::vector<int> idsToFetch1(seedBg,seedEnd);
10772 std::vector<int> idsToFetch2;
10773 std::vector<int> *idsToFetch=&idsToFetch1;
10774 std::vector<int> *idsToFetchOther=&idsToFetch2;
10775 while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
10777 for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
10778 for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
10780 { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
10781 std::swap(idsToFetch,idsToFetchOther);
10782 idsToFetchOther->clear();
10783 nbOfDepthPeelingPerformed++;
10785 int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
10787 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
10788 int *retPtr=ret->getPointer();
10789 for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
10796 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10797 * 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
10798 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
10799 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
10801 * \param [in] start begin of set of ids of the input extraction (included)
10802 * \param [in] end end of set of ids of the input extraction (excluded)
10803 * \param [in] step step of the set of ids in range mode.
10804 * \param [in] arrIn arr origin array from which the extraction will be done.
10805 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10806 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
10807 * \param [in] srcArrIndex index array of \b srcArr
10808 * \param [out] arrOut the resulting array
10809 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10811 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
10813 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10814 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
10815 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10817 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10818 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
10819 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10820 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10821 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10823 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10824 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10825 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
10827 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
10829 if(it>=0 && it<nbOfTuples)
10830 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
10833 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
10834 throw INTERP_KERNEL::Exception(oss.str().c_str());
10837 srcArrIndexPtr=srcArrIndex->getConstPointer();
10838 arrIo->alloc(nbOfTuples+1,1);
10839 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
10840 const int *arrInPtr=arrIn->getConstPointer();
10841 const int *srcArrPtr=srcArr->getConstPointer();
10842 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
10843 int *arroPtr=arro->getPointer();
10844 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
10846 int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
10849 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
10850 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
10854 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
10855 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
10858 arrOut=arro.retn();
10859 arrIndexOut=arrIo.retn();
10863 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10864 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
10866 * \param [in] start begin of set of ids of the input extraction (included)
10867 * \param [in] end end of set of ids of the input extraction (excluded)
10868 * \param [in] step step of the set of ids in range mode.
10869 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
10870 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10871 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
10872 * \param [in] srcArrIndex index array of \b srcArr
10874 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
10876 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
10877 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
10879 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10880 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
10881 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10882 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10883 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10884 int *arrInOutPtr=arrInOut->getPointer();
10885 const int *srcArrPtr=srcArr->getConstPointer();
10886 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
10888 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
10890 if(it>=0 && it<nbOfTuples)
10892 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
10893 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
10896 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
10897 throw INTERP_KERNEL::Exception(oss.str().c_str());
10902 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
10903 throw INTERP_KERNEL::Exception(oss.str().c_str());
10909 * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
10910 * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
10911 * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
10912 * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
10913 * The sum of measure field of returned mesh is equal to the sum of measure field of this.
10915 * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
10917 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
10919 checkFullyDefined();
10920 int mdim=getMeshDimension();
10921 int spaceDim=getSpaceDimension();
10923 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
10924 std::vector<DataArrayInt *> partition=partitionBySpreadZone();
10925 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
10926 std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
10927 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
10928 ret->setCoords(getCoords());
10929 ret->allocateCells((int)partition.size());
10931 for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
10933 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
10934 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
10938 cell=tmp->buildUnionOf2DMesh();
10941 cell=tmp->buildUnionOf3DMesh();
10944 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
10947 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
10950 ret->finishInsertingCells();
10955 * This method partitions \b this into contiguous zone.
10956 * This method only needs a well defined connectivity. Coordinates are not considered here.
10957 * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
10959 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
10961 int nbOfCellsCur=getNumberOfCells();
10962 std::vector<DataArrayInt *> ret;
10963 if(nbOfCellsCur<=0)
10965 DataArrayInt *neigh=0,*neighI=0;
10966 computeNeighborsOfCells(neigh,neighI);
10967 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
10968 std::vector<bool> fetchedCells(nbOfCellsCur,false);
10969 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
10971 while(seed<nbOfCellsCur)
10973 int nbOfPeelPerformed=0;
10974 ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
10975 seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
10977 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
10978 ret.push_back((*it).retn());
10983 * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
10984 * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
10986 * \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.
10987 * \return a newly allocated DataArrayInt to be managed by the caller.
10988 * \throw In case of \a code has not the right format (typically of size 3*n)
10990 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
10992 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
10993 std::size_t nb=code.size()/3;
10994 if(code.size()%3!=0)
10995 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
10996 ret->alloc((int)nb,2);
10997 int *retPtr=ret->getPointer();
10998 for(std::size_t i=0;i<nb;i++,retPtr+=2)
11000 retPtr[0]=code[3*i+2];
11001 retPtr[1]=code[3*i+2]+code[3*i+1];
11007 * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
11008 * All cells in \a this are expected to be linear 3D cells.
11009 * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
11010 * It leads to an increase to number of cells.
11011 * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
11012 * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints
11013 * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
11015 * \param [in] policy - the policy of splitting that must be in (PLANAR_FACE_5, PLANAR_FACE_6, GENERAL_24, GENERAL_48). The policy will be used only for INTERP_KERNEL::NORM_HEXA8 cells.
11016 * For all other cells, the splitting policy will be ignored.
11017 * \param [out] nbOfAdditionalPoints - number of nodes added to \c this->_coords. If > 0 a new coordinates object will be constructed result of the aggregation of the old one and the new points added.
11018 * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
11019 * an id of old cell producing it. The caller is to delete this array using
11020 * decrRef() as it is no more needed.
11021 * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
11023 * \warning This method operates on each cells in this independantly ! So it can leads to non conform mesh in returned value ! If you expect to have a conform mesh in output
11024 * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
11026 * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
11027 * \throw If \a this is not fully constituted with linear 3D cells.
11028 * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
11030 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
11032 INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
11033 checkConnectivityFullyDefined();
11034 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
11035 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
11036 int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
11037 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
11038 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
11039 int *retPt(ret->getPointer());
11040 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
11041 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
11042 const int *oldc(_nodal_connec->begin());
11043 const int *oldci(_nodal_connec_index->begin());
11044 const double *coords(_coords->begin());
11045 for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
11047 std::vector<int> a; std::vector<double> b;
11048 INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
11049 std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
11050 const int *aa(&a[0]);
11053 for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
11055 *it=(-(*(it))-1+nbNodes);
11056 addPts->insertAtTheEnd(b.begin(),b.end());
11057 nbNodes+=(int)b.size()/3;
11059 for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
11060 newConn->insertAtTheEnd(aa,aa+4);
11062 if(!addPts->empty())
11064 addPts->rearrange(3);
11065 nbOfAdditionalPoints=addPts->getNumberOfTuples();
11066 addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
11067 ret0->setCoords(addPts);
11071 nbOfAdditionalPoints=0;
11072 ret0->setCoords(getCoords());
11074 ret0->setNodalConnectivity(newConn);
11076 ret->computeOffsets2();
11077 n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
11078 return ret0.retn();
11082 * It is the linear part of MEDCouplingUMesh::split2DCells. Here no additionnal nodes will be added in \b this. So coordinates pointer remain unchanged (is not even touch).
11084 * \sa MEDCouplingUMesh::split2DCells
11086 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
11088 checkConnectivityFullyDefined();
11089 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
11090 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11091 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11092 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11093 int prevPosOfCi(ciPtr[0]);
11094 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11096 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
11097 *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
11098 for(int j=0;j<sz;j++)
11100 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
11101 for(int k=0;k<sz2;k++)
11102 *cPtr++=subPtr[offset2+k];
11104 *cPtr++=oldConn[prevPosOfCi+j+2];
11107 prevPosOfCi=ciPtr[1];
11108 ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11111 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
11112 _nodal_connec->decrRef();
11113 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
11116 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11122 int ret(nodesCnter++);
11124 e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
11125 addCoo.insertAtTheEnd(newPt,newPt+2);
11132 void EnterTheResultOf2DCellFirst(const INTERP_KERNEL::Edge *e, int start, int stp, int nbOfEdges, bool linOrArc, const double *coords, const int *connBg, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords, std::vector<int>& middles)
11135 int trueStart(start>=0?start:nbOfEdges+start);
11136 tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
11137 newConnOfCell->insertAtTheEnd(tmp,tmp+3);
11142 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11143 InternalAddPoint(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
11144 middles.push_back(tmp3+offset);
11147 middles.push_back(connBg[trueStart+nbOfEdges]);
11151 void EnterTheResultOf2DCellMiddle(const INTERP_KERNEL::Edge *e, int start, int stp, int nbOfEdges, bool linOrArc, const double *coords, const int *connBg, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords, std::vector<int>& middles)
11153 int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
11154 newConnOfCell->pushBackSilent(tmpEnd);
11159 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11160 InternalAddPoint(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11161 middles.push_back(tmp3+offset);
11164 middles.push_back(connBg[start+nbOfEdges]);
11168 void EnterTheResultOf2DCellEnd(const INTERP_KERNEL::Edge *e, int start, int stp, int nbOfEdges, bool linOrArc, const double *coords, const int *connBg, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords, std::vector<int>& middles)
11174 int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
11175 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11176 InternalAddPoint(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11177 middles.push_back(tmp3+offset);
11180 middles.push_back(connBg[start+nbOfEdges]);
11187 * Returns true if a colinearization has been found in the given cell. If false is returned the content pushed in \a newConnOfCell is equal to [ \a connBg , \a connEnd ) .
11188 * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
11190 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
11192 std::size_t sz(std::distance(connBg,connEnd));
11193 if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
11194 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
11196 INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
11197 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
11198 unsigned nbs(cm.getNumberOfSons2(connBg+1,sz)),nbOfHit(0);
11199 int posBaseElt(0),posEndElt(0),nbOfTurn(0);
11200 INTERP_KERNEL::NormalizedCellType typeOfSon;
11201 std::vector<int> middles;
11203 for(;nbOfHit<nbs;nbOfTurn++)
11205 cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
11206 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
11207 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11210 unsigned endI(nbs-nbOfHit);
11211 for(unsigned i=0;i<endI;i++)
11213 cm.fillSonCellNodalConnectivity2(posBaseElt+(int)i+1,connBg+1,sz,tmpConn,typeOfSon);
11214 INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11215 INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11216 bool isColinear(eint->areColinears());
11228 {//look if the first edge of cell is not colinear with last edges in this case the start of nodal connectivity is shifted back
11229 unsigned endII(nbs-nbOfHit-1);//warning nbOfHit can be modified, so put end condition in a variable.
11230 for(unsigned ii=0;ii<endII;ii++)
11232 cm.fillSonCellNodalConnectivity2(nbs-ii-1,connBg+1,sz,tmpConn,typeOfSon);
11233 eCand=MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m);
11234 eint=INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand);
11235 isColinear=eint->areColinears();
11251 //push [posBaseElt,posEndElt) in newConnOfCell using e
11253 EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11254 else if(nbOfHit!=nbs)
11255 EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11257 EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11258 posBaseElt=posEndElt;
11261 if(!middles.empty())
11262 newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
11267 * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
11269 * \return int - the number of new nodes created.
11270 * \sa MEDCouplingUMesh::split2DCells
11272 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
11275 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
11276 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11277 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
11278 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11279 const int *midPtr(mid->begin()),*midIPtr(midI->begin());
11280 const double *oldCoordsPtr(getCoords()->begin());
11281 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11282 int prevPosOfCi(ciPtr[0]);
11283 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11285 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
11286 for(int j=0;j<sz;j++)
11287 { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
11288 *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
11289 for(int j=0;j<sz;j++)//loop over subedges of oldConn
11291 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
11295 cPtr[1]=oldConn[prevPosOfCi+2+j];
11296 cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
11299 std::vector<INTERP_KERNEL::Node *> ns(3);
11300 ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
11301 ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
11302 ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
11303 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
11304 for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
11306 cPtr[1]=subPtr[offset2+k];
11307 cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
11309 int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
11311 { cPtr[1]=tmpEnd; }
11312 cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
11314 prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
11315 ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11318 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
11319 _nodal_connec->decrRef();
11320 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
11321 addCoo->rearrange(2);
11322 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
11324 return addCoo->getNumberOfTuples();
11327 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
11328 _own_cell(true),_cell_id(-1),_nb_cell(0)
11333 _nb_cell=mesh->getNumberOfCells();
11337 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
11345 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
11346 _own_cell(false),_cell_id(bg-1),
11353 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
11356 if(_cell_id<_nb_cell)
11365 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
11371 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
11373 return new MEDCouplingUMeshCellByTypeIterator(_mesh);
11376 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
11382 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
11390 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
11396 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
11401 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
11406 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
11408 return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
11411 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
11416 _nb_cell=mesh->getNumberOfCells();
11420 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
11427 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
11429 const int *c=_mesh->getNodalConnectivity()->getConstPointer();
11430 const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
11431 if(_cell_id<_nb_cell)
11433 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
11434 int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
11435 int startId=_cell_id;
11436 _cell_id+=nbOfElems;
11437 return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
11443 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
11447 _conn=mesh->getNodalConnectivity()->getPointer();
11448 _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
11452 void MEDCouplingUMeshCell::next()
11454 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11459 _conn_lgth=_conn_indx[1]-_conn_indx[0];
11462 std::string MEDCouplingUMeshCell::repr() const
11464 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11466 std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
11468 std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
11472 return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
11475 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
11477 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11478 return (INTERP_KERNEL::NormalizedCellType)_conn[0];
11480 return INTERP_KERNEL::NORM_ERROR;
11483 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
11486 if(_conn_lgth!=NOTICABLE_FIRST_VAL)