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 MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3900 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3902 mw->getBoundingBox(bbox);
3903 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3904 cellIds=mw->getCellsInBoundingBox(bbox,eps);
3908 getBoundingBox(bbox);
3909 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3910 cellIds=getCellsInBoundingBox(bbox,eps);
3912 return cellIds.retn();
3916 * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3917 * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3918 * No consideration of coordinate is done by this method.
3919 * 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)
3920 * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3922 bool MEDCouplingUMesh::isContiguous1D() const
3924 if(getMeshDimension()!=1)
3925 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3926 int nbCells=getNumberOfCells();
3928 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3929 const int *connI=_nodal_connec_index->getConstPointer();
3930 const int *conn=_nodal_connec->getConstPointer();
3931 int ref=conn[connI[0]+2];
3932 for(int i=1;i<nbCells;i++)
3934 if(conn[connI[i]+1]!=ref)
3936 ref=conn[connI[i]+2];
3942 * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3943 * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3944 * \param pt reference point of the line
3945 * \param v normalized director vector of the line
3946 * \param eps max precision before throwing an exception
3947 * \param res output of size this->getNumberOfCells
3949 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3951 if(getMeshDimension()!=1)
3952 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3953 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3954 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3955 if(getSpaceDimension()!=3)
3956 throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3957 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3958 const double *fPtr=f->getArray()->getConstPointer();
3960 for(int i=0;i<getNumberOfCells();i++)
3962 const double *tmp1=fPtr+3*i;
3963 tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3964 tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3965 tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3966 double n1=INTERP_KERNEL::norm<3>(tmp);
3967 n1/=INTERP_KERNEL::norm<3>(tmp1);
3969 throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3971 const double *coo=getCoords()->getConstPointer();
3972 for(int i=0;i<getNumberOfNodes();i++)
3974 std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3975 std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3976 res[i]=std::accumulate(tmp,tmp+3,0.);
3981 * 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.
3982 * \a this is expected to be a mesh so that its space dimension is equal to its
3983 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3984 * 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).
3986 * 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
3987 * 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).
3988 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3990 * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3991 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3993 * \param [in] ptBg the start pointer (included) of the coordinates of the point
3994 * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3995 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3996 * \return the positive value of the distance.
3997 * \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
3999 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
4001 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
4003 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4004 if(meshDim!=spaceDim-1)
4005 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
4006 if(meshDim!=2 && meshDim!=1)
4007 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4008 checkFullyDefined();
4009 if((int)std::distance(ptBg,ptEnd)!=spaceDim)
4010 { 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()); }
4011 DataArrayInt *ret1=0;
4012 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
4013 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
4014 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
4015 cellId=*ret1Safe->begin();
4016 return *ret0->begin();
4020 * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
4021 * to \a this and the first \a cellId in \a this corresponding to the returned distance.
4022 * 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
4023 * 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).
4024 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4026 * \a this is expected to be a mesh so that its space dimension is equal to its
4027 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4028 * 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).
4030 * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
4031 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4033 * \param [in] pts the list of points in which each tuple represents a point
4034 * \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.
4035 * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
4036 * \throw if number of components of \a pts is not equal to the space dimension.
4037 * \throw if mesh dimension of \a this is not equal to space dimension - 1.
4038 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
4040 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
4043 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
4044 pts->checkAllocated();
4045 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4046 if(meshDim!=spaceDim-1)
4047 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
4048 if(meshDim!=2 && meshDim!=1)
4049 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
4050 if(pts->getNumberOfComponents()!=spaceDim)
4052 std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
4053 throw INTERP_KERNEL::Exception(oss.str().c_str());
4055 checkFullyDefined();
4056 int nbCells=getNumberOfCells();
4058 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4059 int nbOfPts=pts->getNumberOfTuples();
4060 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4061 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4062 const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4063 double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4064 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4065 const double *bbox(bboxArr->begin());
4070 BBTreeDst<3> myTree(bbox,0,0,nbCells);
4071 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4073 double x=std::numeric_limits<double>::max();
4074 std::vector<int> elems;
4075 myTree.getMinDistanceOfMax(ptsPtr,x);
4076 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4077 DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4083 BBTreeDst<2> myTree(bbox,0,0,nbCells);
4084 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4086 double x=std::numeric_limits<double>::max();
4087 std::vector<int> elems;
4088 myTree.getMinDistanceOfMax(ptsPtr,x);
4089 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4090 DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4095 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4097 cellIds=ret1.retn();
4102 * \param [in] pt the start pointer (included) of the coordinates of the point
4103 * \param [in] cellIdsBg the start pointer (included) of cellIds
4104 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4105 * \param [in] nc nodal connectivity
4106 * \param [in] ncI nodal connectivity index
4107 * \param [in,out] ret0 the min distance between \a this and the external input point
4108 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4109 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4111 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)
4114 ret0=std::numeric_limits<double>::max();
4115 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4117 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4119 case INTERP_KERNEL::NORM_TRI3:
4121 double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4123 { ret0=tmp; cellId=*zeCell; }
4126 case INTERP_KERNEL::NORM_QUAD4:
4127 case INTERP_KERNEL::NORM_POLYGON:
4129 double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4131 { ret0=tmp; cellId=*zeCell; }
4135 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4141 * \param [in] pt the start pointer (included) of the coordinates of the point
4142 * \param [in] cellIdsBg the start pointer (included) of cellIds
4143 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4144 * \param [in] nc nodal connectivity
4145 * \param [in] ncI nodal connectivity index
4146 * \param [in,out] ret0 the min distance between \a this and the external input point
4147 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4148 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4150 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)
4153 ret0=std::numeric_limits<double>::max();
4154 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4156 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4158 case INTERP_KERNEL::NORM_SEG2:
4160 std::size_t uselessEntry=0;
4161 double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4164 { ret0=tmp; cellId=*zeCell; }
4168 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4174 * Finds cells in contact with a ball (i.e. a point with precision).
4175 * 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.
4176 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4178 * \warning This method is suitable if the caller intends to evaluate only one
4179 * point, for more points getCellsContainingPoints() is recommended as it is
4181 * \param [in] pos - array of coordinates of the ball central point.
4182 * \param [in] eps - ball radius.
4183 * \return int - a smallest id of cells being in contact with the ball, -1 in case
4184 * if there are no such cells.
4185 * \throw If the coordinates array is not set.
4186 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4188 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4190 std::vector<int> elts;
4191 getCellsContainingPoint(pos,eps,elts);
4194 return elts.front();
4198 * Finds cells in contact with a ball (i.e. a point with precision).
4199 * 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.
4200 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4201 * \warning This method is suitable if the caller intends to evaluate only one
4202 * point, for more points getCellsContainingPoints() is recommended as it is
4204 * \param [in] pos - array of coordinates of the ball central point.
4205 * \param [in] eps - ball radius.
4206 * \param [out] elts - vector returning ids of the found cells. It is cleared
4207 * before inserting ids.
4208 * \throw If the coordinates array is not set.
4209 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4211 * \if ENABLE_EXAMPLES
4212 * \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4213 * \ref py_mcumesh_getCellsContainingPoint "Here is a Python example".
4216 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4218 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4219 getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4220 elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4225 namespace ParaMEDMEM
4227 template<const int SPACEDIMM>
4231 static const int MY_SPACEDIM=SPACEDIMM;
4232 static const int MY_MESHDIM=8;
4233 typedef int MyConnType;
4234 static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4236 // useless, but for windows compilation ...
4237 const double* getCoordinatesPtr() const { return 0; }
4238 const int* getConnectivityPtr() const { return 0; }
4239 const int* getConnectivityIndexPtr() const { return 0; }
4240 INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4247 * Warning the nodes in \a m should be decrRefed ! To avoid that Node * pointer be replaced by another instance.
4249 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m)
4251 INTERP_KERNEL::Edge *ret(0);
4252 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]));
4253 m[n0]=bg[0]; m[n1]=bg[1];
4256 case INTERP_KERNEL::NORM_SEG2:
4258 ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4261 case INTERP_KERNEL::NORM_SEG3:
4263 INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4264 INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4265 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4266 // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4267 bool colinearity(inters.areColinears());
4268 delete e1; delete e2;
4270 { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4272 { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4276 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4281 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4283 INTERP_KERNEL::Edge *ret=0;
4286 case INTERP_KERNEL::NORM_SEG2:
4288 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4291 case INTERP_KERNEL::NORM_SEG3:
4293 INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4294 INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4295 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4296 // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4297 bool colinearity=inters.areColinears();
4298 delete e1; delete e2;
4300 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4302 ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4303 mapp2[bg[2]].second=false;
4307 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4313 * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4314 * the global mesh 'mDesc'.
4315 * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4316 * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4318 INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4319 std::map<INTERP_KERNEL::Node *,int>& mapp)
4322 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.
4323 const double *coo=mDesc->getCoords()->getConstPointer();
4324 const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4325 const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4327 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4328 s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4329 for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4331 INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4332 mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4334 INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4335 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4337 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4338 ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4340 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4342 if((*it2).second.second)
4343 mapp[(*it2).second.first]=(*it2).first;
4344 ((*it2).second.first)->decrRef();
4349 INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4353 int locId=nodeId-offset2;
4354 return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4358 int locId=nodeId-offset1;
4359 return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4361 return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4365 * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4367 void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4368 const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4369 /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4371 for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4373 int eltId1=abs(*desc1)-1;
4374 for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4376 std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4377 if(it==mappRev.end())
4379 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4390 template<int SPACEDIM>
4391 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4392 double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4394 elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4395 int *eltsIndexPtr(eltsIndex->getPointer());
4396 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4397 const double *bbox(bboxArr->begin());
4398 int nbOfCells=getNumberOfCells();
4399 const int *conn=_nodal_connec->getConstPointer();
4400 const int *connI=_nodal_connec_index->getConstPointer();
4401 double bb[2*SPACEDIM];
4402 BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4403 for(int i=0;i<nbOfPoints;i++)
4405 eltsIndexPtr[i+1]=eltsIndexPtr[i];
4406 for(int j=0;j<SPACEDIM;j++)
4408 bb[2*j]=pos[SPACEDIM*i+j];
4409 bb[2*j+1]=pos[SPACEDIM*i+j];
4411 std::vector<int> candidates;
4412 myTree.getIntersectingElems(bb,candidates);
4413 for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4415 int sz(connI[(*iter)+1]-connI[*iter]-1);
4416 INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4418 if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4419 status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4423 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4424 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4425 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4426 std::vector<INTERP_KERNEL::Node *> nodes(sz);
4427 INTERP_KERNEL::QuadraticPolygon *pol(0);
4428 for(int j=0;j<sz;j++)
4430 int nodeId(conn[connI[*iter]+1+j]);
4431 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4433 if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4434 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4436 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4437 INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4438 double a(0.),b(0.),c(0.);
4439 a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4440 status=pol->isInOrOut2(n);
4441 delete pol; n->decrRef();
4445 eltsIndexPtr[i+1]++;
4446 elts->pushBackSilent(*iter);
4452 * Finds cells in contact with several balls (i.e. points with precision).
4453 * This method is an extension of getCellContainingPoint() and
4454 * getCellsContainingPoint() for the case of multiple points.
4455 * 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.
4456 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4457 * \param [in] pos - an array of coordinates of points in full interlace mode :
4458 * X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4459 * this->getSpaceDimension() * \a nbOfPoints
4460 * \param [in] nbOfPoints - number of points to locate within \a this mesh.
4461 * \param [in] eps - radius of balls (i.e. the precision).
4462 * \param [out] elts - vector returning ids of found cells.
4463 * \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4464 * dividing cell ids in \a elts into groups each referring to one
4465 * point. Its every element (except the last one) is an index pointing to the
4466 * first id of a group of cells. For example cells in contact with the *i*-th
4467 * point are described by following range of indices:
4468 * [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4469 * \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4470 * Number of cells in contact with the *i*-th point is
4471 * \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4472 * \throw If the coordinates array is not set.
4473 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4475 * \if ENABLE_EXAMPLES
4476 * \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4477 * \ref py_mcumesh_getCellsContainingPoints "Here is a Python example".
4480 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4481 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4483 int spaceDim=getSpaceDimension();
4484 int mDim=getMeshDimension();
4489 const double *coords=_coords->getConstPointer();
4490 getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4497 throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4499 else if(spaceDim==2)
4503 const double *coords=_coords->getConstPointer();
4504 getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4507 throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4509 else if(spaceDim==1)
4513 const double *coords=_coords->getConstPointer();
4514 getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4517 throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4520 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4524 * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4525 * least two its edges intersect each other anywhere except their extremities. An
4526 * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4527 * \param [in,out] cells - a vector returning ids of the found cells. It is not
4528 * cleared before filling in.
4529 * \param [in] eps - precision.
4530 * \throw If \a this->getMeshDimension() != 2.
4531 * \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4533 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4535 const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4536 if(getMeshDimension()!=2)
4537 throw INTERP_KERNEL::Exception(msg);
4538 int spaceDim=getSpaceDimension();
4539 if(spaceDim!=2 && spaceDim!=3)
4540 throw INTERP_KERNEL::Exception(msg);
4541 const int *conn=_nodal_connec->getConstPointer();
4542 const int *connI=_nodal_connec_index->getConstPointer();
4543 int nbOfCells=getNumberOfCells();
4544 std::vector<double> cell2DinS2;
4545 for(int i=0;i<nbOfCells;i++)
4547 int offset=connI[i];
4548 int nbOfNodesForCell=connI[i+1]-offset-1;
4549 if(nbOfNodesForCell<=3)
4551 bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4552 project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4553 if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4560 * This method is typically requested to unbutterfly 2D linear cells in \b this.
4562 * 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.
4563 * 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.
4565 * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4566 * This convex envelop is computed using Jarvis march algorithm.
4567 * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4568 * 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)
4569 * 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.
4571 * \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.
4572 * \sa MEDCouplingUMesh::colinearize2D
4574 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4576 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4577 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D works only for meshDim=2 and spaceDim=2 !");
4578 checkFullyDefined();
4579 const double *coords=getCoords()->getConstPointer();
4580 int nbOfCells=getNumberOfCells();
4581 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4582 nodalConnecIndexOut->alloc(nbOfCells+1,1);
4583 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4584 int *workIndexOut=nodalConnecIndexOut->getPointer();
4586 const int *nodalConnecIn=_nodal_connec->getConstPointer();
4587 const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4588 std::set<INTERP_KERNEL::NormalizedCellType> types;
4589 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4590 isChanged->alloc(0,1);
4591 for(int i=0;i<nbOfCells;i++,workIndexOut++)
4593 int pos=nodalConnecOut->getNumberOfTuples();
4594 if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4595 isChanged->pushBackSilent(i);
4596 types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4597 workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4599 if(isChanged->empty())
4601 setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4603 return isChanged.retn();
4607 * This method is \b NOT const because it can modify \a this.
4608 * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4609 * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4610 * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4611 * \b 1 for translation and rotation around point of 'mesh1D'.
4612 * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.
4614 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4616 checkFullyDefined();
4617 mesh1D->checkFullyDefined();
4618 if(!mesh1D->isContiguous1D())
4619 throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4620 if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4621 throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4622 if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4623 throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4624 if(mesh1D->getMeshDimension()!=1)
4625 throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4627 if(isPresenceOfQuadratic())
4629 if(mesh1D->isFullyQuadratic())
4632 throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4635 int oldNbOfNodes=getNumberOfNodes();
4636 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4641 newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4646 newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4650 throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4652 setCoords(newCoords);
4653 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4659 * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4660 * If it is not the case an exception will be thrown.
4661 * This method is non const because the coordinate of \a this can be appended with some new points issued from
4662 * intersection of plane defined by ('origin','vec').
4663 * This method has one in/out parameter : 'cut3DCurve'.
4664 * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4665 * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4666 * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4667 * This method will throw an exception if \a this contains a non linear segment.
4669 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4671 checkFullyDefined();
4672 if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4673 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4674 int ncells=getNumberOfCells();
4675 int nnodes=getNumberOfNodes();
4676 double vec2[3],vec3[3],vec4[3];
4677 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4679 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4680 vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4681 const int *conn=_nodal_connec->getConstPointer();
4682 const int *connI=_nodal_connec_index->getConstPointer();
4683 const double *coo=_coords->getConstPointer();
4684 std::vector<double> addCoo;
4685 for(int i=0;i<ncells;i++)
4687 if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4689 if(cut3DCurve[i]==-2)
4691 int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4692 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];
4693 double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4694 double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4695 if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4697 const double *st2=coo+3*st;
4698 vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4699 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]));
4700 if(pos>eps && pos<1-eps)
4702 int nNode=((int)addCoo.size())/3;
4703 vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4704 addCoo.insert(addCoo.end(),vec4,vec4+3);
4705 cut3DCurve[i]=nnodes+nNode;
4711 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4715 int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4716 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4717 coo2->alloc(newNbOfNodes,3);
4718 double *tmp=coo2->getPointer();
4719 tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4720 std::copy(addCoo.begin(),addCoo.end(),tmp);
4721 DataArrayDouble::SetArrayIn(coo2,_coords);
4726 * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4727 * \param mesh1D is the input 1D mesh used for translation computation.
4728 * \return newCoords new coords filled by this method.
4730 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4732 int oldNbOfNodes=getNumberOfNodes();
4733 int nbOf1DCells=mesh1D->getNumberOfCells();
4734 int spaceDim=getSpaceDimension();
4735 DataArrayDouble *ret=DataArrayDouble::New();
4736 std::vector<bool> isQuads;
4737 int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4738 ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4739 double *retPtr=ret->getPointer();
4740 const double *coords=getCoords()->getConstPointer();
4741 double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4743 std::vector<double> c;
4747 for(int i=0;i<nbOf1DCells;i++)
4750 mesh1D->getNodeIdsOfCell(i,v);
4752 mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4753 mesh1D->getCoordinatesOfNode(v[0],c);
4754 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4755 for(int j=0;j<oldNbOfNodes;j++)
4756 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4760 mesh1D->getCoordinatesOfNode(v[1],c);
4761 mesh1D->getCoordinatesOfNode(v[0],c);
4762 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4763 for(int j=0;j<oldNbOfNodes;j++)
4764 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4767 ret->copyStringInfoFrom(*getCoords());
4772 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4773 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4774 * \return newCoords new coords filled by this method.
4776 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4778 if(mesh1D->getSpaceDimension()==2)
4779 return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4780 if(mesh1D->getSpaceDimension()==3)
4781 return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4782 throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4786 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4787 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4788 * \return newCoords new coords filled by this method.
4790 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4793 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4794 int oldNbOfNodes=getNumberOfNodes();
4795 int nbOf1DCells=mesh1D->getNumberOfCells();
4797 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4798 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4799 int nbOfLevsInVec=nbOf1DCells+1;
4800 ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4801 double *retPtr=ret->getPointer();
4802 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4803 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4804 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4805 tmp->setCoords(tmp2);
4806 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4807 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4808 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4809 for(int i=1;i<nbOfLevsInVec;i++)
4811 const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4812 const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4813 const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4814 const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4815 tmp->translate(vec);
4816 double tmp3[2],radius,alpha,alpha0;
4817 const double *p0=i+1<nbOfLevsInVec?begin:third;
4818 const double *p1=i+1<nbOfLevsInVec?end:begin;
4819 const double *p2=i+1<nbOfLevsInVec?third:end;
4820 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4821 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]);
4822 double angle=acos(cosangle/(radius*radius));
4823 tmp->rotate(end,0,angle);
4824 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4830 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4831 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4832 * \return newCoords new coords filled by this method.
4834 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4837 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4838 int oldNbOfNodes=getNumberOfNodes();
4839 int nbOf1DCells=mesh1D->getNumberOfCells();
4841 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4842 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4843 int nbOfLevsInVec=nbOf1DCells+1;
4844 ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4845 double *retPtr=ret->getPointer();
4846 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4847 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4848 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4849 tmp->setCoords(tmp2);
4850 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4851 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4852 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4853 for(int i=1;i<nbOfLevsInVec;i++)
4855 const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4856 const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4857 const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4858 const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4859 tmp->translate(vec);
4860 double tmp3[2],radius,alpha,alpha0;
4861 const double *p0=i+1<nbOfLevsInVec?begin:third;
4862 const double *p1=i+1<nbOfLevsInVec?end:begin;
4863 const double *p2=i+1<nbOfLevsInVec?third:end;
4864 double vecPlane[3]={
4865 (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4866 (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4867 (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4869 double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4872 vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4873 double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4874 double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4876 double c2=cos(asin(s2));
4878 {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4879 {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4880 {-vec2[1]*s2, vec2[0]*s2, c2}
4882 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]};
4883 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]};
4884 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]};
4885 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4886 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]);
4887 double angle=acos(cosangle/(radius*radius));
4888 tmp->rotate(end,vecPlane,angle);
4890 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4896 * This method is private because not easy to use for end user. This method is const contrary to
4897 * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4898 * the coords sorted slice by slice.
4899 * \param isQuad specifies presence of quadratic cells.
4901 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4903 int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4904 int nbOf2DCells=getNumberOfCells();
4905 int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4906 MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4907 const int *conn=_nodal_connec->getConstPointer();
4908 const int *connI=_nodal_connec_index->getConstPointer();
4909 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4910 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4911 newConnI->alloc(nbOf3DCells+1,1);
4912 int *newConnIPtr=newConnI->getPointer();
4914 std::vector<int> newc;
4915 for(int j=0;j<nbOf2DCells;j++)
4917 AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4918 *newConnIPtr++=(int)newc.size();
4920 newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4921 int *newConnPtr=newConn->getPointer();
4922 int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4923 newConnIPtr=newConnI->getPointer();
4924 for(int iz=0;iz<nbOf1DCells;iz++)
4927 std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4928 for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4930 int icell=(int)(iter-newc.begin());
4931 if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4934 *newConnPtr=(*iter)+iz*deltaPerLev;
4939 *newConnPtr=(*iter);
4942 ret->setConnectivity(newConn,newConnI,true);
4943 ret->setCoords(getCoords());
4948 * Checks if \a this mesh is constituted by only quadratic cells.
4949 * \return bool - \c true if there are only quadratic cells in \a this mesh.
4950 * \throw If the coordinates array is not set.
4951 * \throw If the nodal connectivity of cells is not defined.
4953 bool MEDCouplingUMesh::isFullyQuadratic() const
4955 checkFullyDefined();
4957 int nbOfCells=getNumberOfCells();
4958 for(int i=0;i<nbOfCells && ret;i++)
4960 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4961 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4962 ret=cm.isQuadratic();
4968 * Checks if \a this mesh includes any quadratic cell.
4969 * \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4970 * \throw If the coordinates array is not set.
4971 * \throw If the nodal connectivity of cells is not defined.
4973 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4975 checkFullyDefined();
4977 int nbOfCells=getNumberOfCells();
4978 for(int i=0;i<nbOfCells && !ret;i++)
4980 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4981 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4982 ret=cm.isQuadratic();
4988 * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4989 * this mesh, it remains unchanged.
4990 * \throw If the coordinates array is not set.
4991 * \throw If the nodal connectivity of cells is not defined.
4993 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4995 checkFullyDefined();
4996 int nbOfCells=getNumberOfCells();
4998 const int *iciptr=_nodal_connec_index->getConstPointer();
4999 for(int i=0;i<nbOfCells;i++)
5001 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5002 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5003 if(cm.isQuadratic())
5005 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5006 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5007 if(!cml.isDynamic())
5008 delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
5010 delta+=(iciptr[i+1]-iciptr[i]-1)/2;
5015 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5016 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5017 const int *icptr=_nodal_connec->getConstPointer();
5018 newConn->alloc(getMeshLength()-delta,1);
5019 newConnI->alloc(nbOfCells+1,1);
5020 int *ocptr=newConn->getPointer();
5021 int *ociptr=newConnI->getPointer();
5024 for(int i=0;i<nbOfCells;i++,ociptr++)
5026 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
5027 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5028 if(!cm.isQuadratic())
5030 _types.insert(type);
5031 ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5032 ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5036 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5037 _types.insert(typel);
5038 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5039 int newNbOfNodes=cml.getNumberOfNodes();
5041 newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
5042 *ocptr++=(int)typel;
5043 ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5044 ociptr[1]=ociptr[0]+newNbOfNodes+1;
5047 setConnectivity(newConn,newConnI,false);
5051 * This method converts all linear cell in \a this to quadratic one.
5052 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5053 * 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)
5054 * 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.
5055 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5056 * end of the existing coordinates.
5058 * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5059 * corresponding quadratic cells. 1 is those creating the 'most' complex.
5060 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5062 * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5064 * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5066 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5068 DataArrayInt *conn=0,*connI=0;
5069 DataArrayDouble *coords=0;
5070 std::set<INTERP_KERNEL::NormalizedCellType> types;
5071 checkFullyDefined();
5072 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5073 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5074 int meshDim=getMeshDimension();
5075 switch(conversionType)
5081 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5082 connSafe=conn; connISafe=connI; coordsSafe=coords;
5085 ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5086 connSafe=conn; connISafe=connI; coordsSafe=coords;
5089 ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5090 connSafe=conn; connISafe=connI; coordsSafe=coords;
5093 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5101 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5102 connSafe=conn; connISafe=connI; coordsSafe=coords;
5105 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5106 connSafe=conn; connISafe=connI; coordsSafe=coords;
5109 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5110 connSafe=conn; connISafe=connI; coordsSafe=coords;
5113 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5118 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5120 setConnectivity(connSafe,connISafe,false);
5122 setCoords(coordsSafe);
5128 * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
5129 * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
5130 * The nodes to be added in those 2D cells are defined by the pair of \a nodeIdsToAdd and \a nodeIdsIndexToAdd.
5131 * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
5132 * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
5133 * This method can be seen as the opposite method of colinearize2D.
5134 * 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
5135 * to avoid to modify the numbering of existing nodes.
5137 * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
5138 * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
5139 * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
5140 * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
5141 * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
5142 * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
5143 * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
5145 * \sa buildDescendingConnectivity2
5147 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
5148 const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
5150 if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
5151 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
5152 nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
5153 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
5154 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
5155 if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
5156 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
5157 //DataArrayInt *out0(0),*outi0(0);
5158 //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
5159 //MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s(out0),outi0s(outi0);
5160 //out0s=out0s->buildUnique(); out0s->sort(true);
5165 * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5166 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5167 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5169 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5171 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5172 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5173 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5174 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5175 int nbOfCells=getNumberOfCells();
5176 int nbOfNodes=getNumberOfNodes();
5177 const int *cPtr=_nodal_connec->getConstPointer();
5178 const int *icPtr=_nodal_connec_index->getConstPointer();
5179 int lastVal=0,offset=nbOfNodes;
5180 for(int i=0;i<nbOfCells;i++,icPtr++)
5182 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5183 if(type==INTERP_KERNEL::NORM_SEG2)
5185 types.insert(INTERP_KERNEL::NORM_SEG3);
5186 newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5187 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5188 newConn->pushBackSilent(offset++);
5190 newConnI->pushBackSilent(lastVal);
5191 ret->pushBackSilent(i);
5196 lastVal+=(icPtr[1]-icPtr[0]);
5197 newConnI->pushBackSilent(lastVal);
5198 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5201 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5202 coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5206 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
5208 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5209 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5210 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5212 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5213 DataArrayInt *conn1D=0,*conn1DI=0;
5214 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5215 DataArrayDouble *coordsTmp=0;
5216 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5217 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5218 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5219 const int *c1DPtr=conn1D->begin();
5220 const int *c1DIPtr=conn1DI->begin();
5221 int nbOfCells=getNumberOfCells();
5222 const int *cPtr=_nodal_connec->getConstPointer();
5223 const int *icPtr=_nodal_connec_index->getConstPointer();
5225 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5227 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5228 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5229 if(!cm.isQuadratic())
5231 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5232 types.insert(typ2); newConn->pushBackSilent(typ2);
5233 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5234 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5235 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5236 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5237 newConnI->pushBackSilent(lastVal);
5238 ret->pushBackSilent(i);
5243 lastVal+=(icPtr[1]-icPtr[0]);
5244 newConnI->pushBackSilent(lastVal);
5245 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5248 conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5253 * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5254 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5255 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5257 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5259 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5260 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5261 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5264 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5266 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5267 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5269 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5270 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5271 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5273 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5274 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5275 DataArrayInt *conn1D=0,*conn1DI=0;
5276 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5277 DataArrayDouble *coordsTmp=0;
5278 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5279 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5280 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5281 const int *c1DPtr=conn1D->begin();
5282 const int *c1DIPtr=conn1DI->begin();
5283 int nbOfCells=getNumberOfCells();
5284 const int *cPtr=_nodal_connec->getConstPointer();
5285 const int *icPtr=_nodal_connec_index->getConstPointer();
5286 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5287 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5289 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5290 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5291 if(!cm.isQuadratic())
5293 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5294 types.insert(typ2); newConn->pushBackSilent(typ2);
5295 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5296 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5297 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5298 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5299 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5300 newConnI->pushBackSilent(lastVal);
5301 ret->pushBackSilent(i);
5306 lastVal+=(icPtr[1]-icPtr[0]);
5307 newConnI->pushBackSilent(lastVal);
5308 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5311 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5312 coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5317 * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5318 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5319 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5321 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5323 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5324 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5325 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5328 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5330 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5331 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5332 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5333 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5335 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5336 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5337 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5339 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5340 const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5341 DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5342 std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5343 DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5344 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5345 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5346 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5347 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5348 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5349 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5350 const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5351 int nbOfCells=getNumberOfCells();
5352 const int *cPtr=_nodal_connec->getConstPointer();
5353 const int *icPtr=_nodal_connec_index->getConstPointer();
5354 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5355 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5357 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5358 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5359 if(!cm.isQuadratic())
5361 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5362 if(typ2==INTERP_KERNEL::NORM_ERROR)
5364 std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5365 throw INTERP_KERNEL::Exception(oss.str().c_str());
5367 types.insert(typ2); newConn->pushBackSilent(typ2);
5368 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5369 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5370 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5371 for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5373 int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5374 int tmpPos=newConn->getNumberOfTuples();
5375 newConn->pushBackSilent(nodeId2);
5376 ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5378 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5379 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5380 newConnI->pushBackSilent(lastVal);
5381 ret->pushBackSilent(i);
5386 lastVal+=(icPtr[1]-icPtr[0]);
5387 newConnI->pushBackSilent(lastVal);
5388 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5391 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5392 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5393 coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5394 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5395 std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5396 int *c=newConn->getPointer();
5397 const int *cI(newConnI->begin());
5398 for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5399 c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5400 offset=coordsTmp2Safe->getNumberOfTuples();
5401 for(const int *elt=ret->begin();elt!=ret->end();elt++)
5402 c[cI[(*elt)+1]-1]+=offset;
5403 coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5408 * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5409 * so that the number of cells remains the same. Quadratic faces are converted to
5410 * polygons. This method works only for 2D meshes in
5411 * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5412 * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5413 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5414 * \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5415 * a polylinized edge constituting the input polygon.
5416 * \throw If the coordinates array is not set.
5417 * \throw If the nodal connectivity of cells is not defined.
5418 * \throw If \a this->getMeshDimension() != 2.
5419 * \throw If \a this->getSpaceDimension() != 2.
5421 void MEDCouplingUMesh::tessellate2D(double eps)
5423 checkFullyDefined();
5424 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
5425 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5426 double epsa=fabs(eps);
5427 if(epsa<std::numeric_limits<double>::min())
5428 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 !");
5429 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5430 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5431 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5432 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5433 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5434 revDesc1=0; revDescIndx1=0;
5435 mDesc->tessellate2DCurve(eps);
5436 subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5437 setCoords(mDesc->getCoords());
5441 * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5442 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5443 * \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5444 * a sub-divided edge.
5445 * \throw If the coordinates array is not set.
5446 * \throw If the nodal connectivity of cells is not defined.
5447 * \throw If \a this->getMeshDimension() != 1.
5448 * \throw If \a this->getSpaceDimension() != 2.
5450 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5452 checkFullyDefined();
5453 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5454 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5455 double epsa=fabs(eps);
5456 if(epsa<std::numeric_limits<double>::min())
5457 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 !");
5458 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5459 int nbCells=getNumberOfCells();
5460 int nbNodes=getNumberOfNodes();
5461 const int *conn=_nodal_connec->getConstPointer();
5462 const int *connI=_nodal_connec_index->getConstPointer();
5463 const double *coords=_coords->getConstPointer();
5464 std::vector<double> addCoo;
5465 std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5466 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5467 newConnI->alloc(nbCells+1,1);
5468 int *newConnIPtr=newConnI->getPointer();
5471 INTERP_KERNEL::Node *tmp2[3];
5472 std::set<INTERP_KERNEL::NormalizedCellType> types;
5473 for(int i=0;i<nbCells;i++,newConnIPtr++)
5475 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5476 if(cm.isQuadratic())
5477 {//assert(connI[i+1]-connI[i]-1==3)
5478 tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5479 tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5480 tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5481 tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5482 INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5485 eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5486 types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5488 newConnIPtr[1]=(int)newConn.size();
5492 types.insert(INTERP_KERNEL::NORM_SEG2);
5493 newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5494 newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5495 newConnIPtr[1]=newConnIPtr[0]+3;
5500 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5501 newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5502 newConnIPtr[1]=newConnIPtr[0]+3;
5505 if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5508 DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5509 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5510 newConnArr->alloc((int)newConn.size(),1);
5511 std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5512 DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5513 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5514 newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5515 double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5516 std::copy(addCoo.begin(),addCoo.end(),work);
5517 DataArrayDouble::SetArrayIn(newCoords,_coords);
5522 * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5523 * In addition, returns an array mapping new cells to old ones. <br>
5524 * This method typically increases the number of cells in \a this mesh
5525 * but the number of nodes remains \b unchanged.
5526 * That's why the 3D splitting policies
5527 * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5528 * \param [in] policy - specifies a pattern used for splitting.
5529 * The semantic of \a policy is:
5530 * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5531 * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5532 * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8 into 5 TETRA4 (for 3D mesh only).
5533 * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8 into 6 TETRA4 (for 3D mesh only).
5534 * \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5535 * an id of old cell producing it. The caller is to delete this array using
5536 * decrRef() as it is no more needed.
5537 * \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5538 * \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5539 * and \a this->getMeshDimension() != 3.
5540 * \throw If \a policy is not one of the four discussed above.
5541 * \throw If the nodal connectivity of cells is not defined.
5542 * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5544 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5549 return simplexizePol0();
5551 return simplexizePol1();
5552 case (int) INTERP_KERNEL::PLANAR_FACE_5:
5553 return simplexizePlanarFace5();
5554 case (int) INTERP_KERNEL::PLANAR_FACE_6:
5555 return simplexizePlanarFace6();
5557 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)");
5562 * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5563 * - 1D: INTERP_KERNEL::NORM_SEG2
5564 * - 2D: INTERP_KERNEL::NORM_TRI3
5565 * - 3D: INTERP_KERNEL::NORM_TETRA4.
5567 * This method is useful for users that need to use P1 field services as
5568 * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5569 * All these methods need mesh support containing only simplex cells.
5570 * \return bool - \c true if there are only simplex cells in \a this mesh.
5571 * \throw If the coordinates array is not set.
5572 * \throw If the nodal connectivity of cells is not defined.
5573 * \throw If \a this->getMeshDimension() < 1.
5575 bool MEDCouplingUMesh::areOnlySimplexCells() const
5577 checkFullyDefined();
5578 int mdim=getMeshDimension();
5579 if(mdim<1 || mdim>3)
5580 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5581 int nbCells=getNumberOfCells();
5582 const int *conn=_nodal_connec->getConstPointer();
5583 const int *connI=_nodal_connec_index->getConstPointer();
5584 for(int i=0;i<nbCells;i++)
5586 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5594 * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5596 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5598 checkConnectivityFullyDefined();
5599 if(getMeshDimension()!=2)
5600 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5601 int nbOfCells=getNumberOfCells();
5602 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5603 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5604 ret->alloc(nbOfCells+nbOfCutCells,1);
5605 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5606 int *retPt=ret->getPointer();
5607 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5608 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5609 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5610 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5611 int *pt=newConn->getPointer();
5612 int *ptI=newConnI->getPointer();
5614 const int *oldc=_nodal_connec->getConstPointer();
5615 const int *ci=_nodal_connec_index->getConstPointer();
5616 for(int i=0;i<nbOfCells;i++,ci++)
5618 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5620 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5621 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5622 pt=std::copy(tmp,tmp+8,pt);
5631 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5632 ptI[1]=ptI[0]+ci[1]-ci[0];
5637 _nodal_connec->decrRef();
5638 _nodal_connec=newConn.retn();
5639 _nodal_connec_index->decrRef();
5640 _nodal_connec_index=newConnI.retn();
5647 * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5649 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5651 checkConnectivityFullyDefined();
5652 if(getMeshDimension()!=2)
5653 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5654 int nbOfCells=getNumberOfCells();
5655 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5656 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5657 ret->alloc(nbOfCells+nbOfCutCells,1);
5658 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5659 int *retPt=ret->getPointer();
5660 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5661 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5662 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5663 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5664 int *pt=newConn->getPointer();
5665 int *ptI=newConnI->getPointer();
5667 const int *oldc=_nodal_connec->getConstPointer();
5668 const int *ci=_nodal_connec_index->getConstPointer();
5669 for(int i=0;i<nbOfCells;i++,ci++)
5671 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5673 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5674 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5675 pt=std::copy(tmp,tmp+8,pt);
5684 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5685 ptI[1]=ptI[0]+ci[1]-ci[0];
5690 _nodal_connec->decrRef();
5691 _nodal_connec=newConn.retn();
5692 _nodal_connec_index->decrRef();
5693 _nodal_connec_index=newConnI.retn();
5700 * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5702 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5704 checkConnectivityFullyDefined();
5705 if(getMeshDimension()!=3)
5706 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5707 int nbOfCells=getNumberOfCells();
5708 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5709 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5710 ret->alloc(nbOfCells+4*nbOfCutCells,1);
5711 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5712 int *retPt=ret->getPointer();
5713 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5714 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5715 newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5716 newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5717 int *pt=newConn->getPointer();
5718 int *ptI=newConnI->getPointer();
5720 const int *oldc=_nodal_connec->getConstPointer();
5721 const int *ci=_nodal_connec_index->getConstPointer();
5722 for(int i=0;i<nbOfCells;i++,ci++)
5724 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5726 for(int j=0;j<5;j++,pt+=5,ptI++)
5728 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5729 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];
5736 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5737 ptI[1]=ptI[0]+ci[1]-ci[0];
5742 _nodal_connec->decrRef();
5743 _nodal_connec=newConn.retn();
5744 _nodal_connec_index->decrRef();
5745 _nodal_connec_index=newConnI.retn();
5752 * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5754 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5756 checkConnectivityFullyDefined();
5757 if(getMeshDimension()!=3)
5758 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5759 int nbOfCells=getNumberOfCells();
5760 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5761 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5762 ret->alloc(nbOfCells+5*nbOfCutCells,1);
5763 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5764 int *retPt=ret->getPointer();
5765 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5766 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5767 newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5768 newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5769 int *pt=newConn->getPointer();
5770 int *ptI=newConnI->getPointer();
5772 const int *oldc=_nodal_connec->getConstPointer();
5773 const int *ci=_nodal_connec_index->getConstPointer();
5774 for(int i=0;i<nbOfCells;i++,ci++)
5776 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5778 for(int j=0;j<6;j++,pt+=5,ptI++)
5780 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5781 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];
5788 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5789 ptI[1]=ptI[0]+ci[1]-ci[0];
5794 _nodal_connec->decrRef();
5795 _nodal_connec=newConn.retn();
5796 _nodal_connec_index->decrRef();
5797 _nodal_connec_index=newConnI.retn();
5804 * 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.
5805 * This method completly ignore coordinates.
5806 * \param nodeSubdived is the nodal connectivity of subdivision of edges
5807 * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5808 * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5809 * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5811 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5813 checkFullyDefined();
5814 if(getMeshDimension()!=2)
5815 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5816 int nbOfCells=getNumberOfCells();
5817 int *connI=_nodal_connec_index->getPointer();
5819 for(int i=0;i<nbOfCells;i++,connI++)
5821 int offset=descIndex[i];
5822 int nbOfEdges=descIndex[i+1]-offset;
5824 bool ddirect=desc[offset+nbOfEdges-1]>0;
5825 int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5826 int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5827 for(int j=0;j<nbOfEdges;j++)
5829 bool direct=desc[offset+j]>0;
5830 int edgeId=std::abs(desc[offset+j])-1;
5831 if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5833 int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5834 int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5835 int ref2=direct?id1:id2;
5838 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5839 newConnLgth+=nbOfSubNodes-1;
5844 std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5845 throw INTERP_KERNEL::Exception(oss.str().c_str());
5850 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5853 newConnLgth++;//+1 is for cell type
5854 connI[1]=newConnLgth;
5857 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5858 newConn->alloc(newConnLgth,1);
5859 int *work=newConn->getPointer();
5860 for(int i=0;i<nbOfCells;i++)
5862 *work++=INTERP_KERNEL::NORM_POLYGON;
5863 int offset=descIndex[i];
5864 int nbOfEdges=descIndex[i+1]-offset;
5865 for(int j=0;j<nbOfEdges;j++)
5867 bool direct=desc[offset+j]>0;
5868 int edgeId=std::abs(desc[offset+j])-1;
5870 work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5873 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5874 std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5875 work=std::copy(it,it+nbOfSubNodes-1,work);
5879 DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5882 _types.insert(INTERP_KERNEL::NORM_POLYGON);
5886 * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5887 * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5888 * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5889 * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5890 * so it can be useful to call mergeNodes() before calling this method.
5891 * \throw If \a this->getMeshDimension() <= 1.
5892 * \throw If the coordinates array is not set.
5893 * \throw If the nodal connectivity of cells is not defined.
5895 void MEDCouplingUMesh::convertDegeneratedCells()
5897 checkFullyDefined();
5898 if(getMeshDimension()<=1)
5899 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5900 int nbOfCells=getNumberOfCells();
5903 int initMeshLgth=getMeshLength();
5904 int *conn=_nodal_connec->getPointer();
5905 int *index=_nodal_connec_index->getPointer();
5909 for(int i=0;i<nbOfCells;i++)
5911 lgthOfCurCell=index[i+1]-posOfCurCell;
5912 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5914 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5915 conn+newPos+1,newLgth);
5916 conn[newPos]=newType;
5918 posOfCurCell=index[i+1];
5921 if(newPos!=initMeshLgth)
5922 _nodal_connec->reAlloc(newPos);
5927 * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5928 * A cell is considered to be oriented correctly if an angle between its
5929 * normal vector and a given vector is less than \c PI / \c 2.
5930 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5932 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5934 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5935 * is not cleared before filling in.
5936 * \throw If \a this->getMeshDimension() != 2.
5937 * \throw If \a this->getSpaceDimension() != 3.
5939 * \if ENABLE_EXAMPLES
5940 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5941 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5944 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
5946 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5947 throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5948 int nbOfCells=getNumberOfCells();
5949 const int *conn=_nodal_connec->getConstPointer();
5950 const int *connI=_nodal_connec_index->getConstPointer();
5951 const double *coordsPtr=_coords->getConstPointer();
5952 for(int i=0;i<nbOfCells;i++)
5954 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5955 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5957 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5958 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5965 * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5966 * considered to be oriented correctly if an angle between its normal vector and a
5967 * given vector is less than \c PI / \c 2.
5968 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5970 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5972 * \throw If \a this->getMeshDimension() != 2.
5973 * \throw If \a this->getSpaceDimension() != 3.
5975 * \if ENABLE_EXAMPLES
5976 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5977 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5980 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
5982 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5983 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5984 int nbOfCells=getNumberOfCells();
5985 int *conn=_nodal_connec->getPointer();
5986 const int *connI=_nodal_connec_index->getConstPointer();
5987 const double *coordsPtr=_coords->getConstPointer();
5988 bool isModified=false;
5989 for(int i=0;i<nbOfCells;i++)
5991 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5992 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5994 bool isQuadratic(INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic());
5995 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6000 std::vector<int> tmp(connI[i+1]-connI[i]-2);
6001 std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
6002 std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
6006 int sz(((int)(connI[i+1]-connI[i]-1))/2);
6007 std::vector<int> tmp0(sz-1),tmp1(sz);
6008 std::copy(conn+connI[i]+2,conn+connI[i]+1+sz,tmp0.rbegin());
6009 std::copy(conn+connI[i]+1+sz,conn+connI[i+1],tmp1.rbegin());
6010 std::copy(tmp0.begin(),tmp0.end(),conn+connI[i]+2);
6011 std::copy(tmp1.begin(),tmp1.end(),conn+connI[i]+1+sz);
6017 _nodal_connec->declareAsNew();
6022 * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
6023 * oriented facets. The normal vector of the facet should point out of the cell.
6024 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6025 * is not cleared before filling in.
6026 * \throw If \a this->getMeshDimension() != 3.
6027 * \throw If \a this->getSpaceDimension() != 3.
6028 * \throw If the coordinates array is not set.
6029 * \throw If the nodal connectivity of cells is not defined.
6031 * \if ENABLE_EXAMPLES
6032 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6033 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6036 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
6038 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6039 throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
6040 int nbOfCells=getNumberOfCells();
6041 const int *conn=_nodal_connec->getConstPointer();
6042 const int *connI=_nodal_connec_index->getConstPointer();
6043 const double *coordsPtr=_coords->getConstPointer();
6044 for(int i=0;i<nbOfCells;i++)
6046 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6047 if(type==INTERP_KERNEL::NORM_POLYHED)
6049 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6056 * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6058 * \throw If \a this->getMeshDimension() != 3.
6059 * \throw If \a this->getSpaceDimension() != 3.
6060 * \throw If the coordinates array is not set.
6061 * \throw If the nodal connectivity of cells is not defined.
6062 * \throw If the reparation fails.
6064 * \if ENABLE_EXAMPLES
6065 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6066 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6068 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6070 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
6072 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6073 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6074 int nbOfCells=getNumberOfCells();
6075 int *conn=_nodal_connec->getPointer();
6076 const int *connI=_nodal_connec_index->getConstPointer();
6077 const double *coordsPtr=_coords->getConstPointer();
6078 for(int i=0;i<nbOfCells;i++)
6080 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6081 if(type==INTERP_KERNEL::NORM_POLYHED)
6085 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6086 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6088 catch(INTERP_KERNEL::Exception& e)
6090 std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6091 throw INTERP_KERNEL::Exception(oss.str().c_str());
6099 * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6100 * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6101 * according to which the first facet of the cell should be oriented to have the normal vector
6102 * pointing out of cell.
6103 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6104 * cells. The caller is to delete this array using decrRef() as it is no more
6106 * \throw If \a this->getMeshDimension() != 3.
6107 * \throw If \a this->getSpaceDimension() != 3.
6108 * \throw If the coordinates array is not set.
6109 * \throw If the nodal connectivity of cells is not defined.
6111 * \if ENABLE_EXAMPLES
6112 * \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6113 * \ref py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6115 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6117 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6119 const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6120 if(getMeshDimension()!=3)
6121 throw INTERP_KERNEL::Exception(msg);
6122 int spaceDim=getSpaceDimension();
6124 throw INTERP_KERNEL::Exception(msg);
6126 int nbOfCells=getNumberOfCells();
6127 int *conn=_nodal_connec->getPointer();
6128 const int *connI=_nodal_connec_index->getConstPointer();
6129 const double *coo=getCoords()->getConstPointer();
6130 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6131 for(int i=0;i<nbOfCells;i++)
6133 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6134 if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6136 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6138 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6139 cells->pushBackSilent(i);
6143 return cells.retn();
6147 * This method is a faster method to correct orientation of all 3D cells in \a this.
6148 * 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.
6149 * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6151 * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6152 * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons,
6154 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6156 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6157 throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6158 int nbOfCells=getNumberOfCells();
6159 int *conn=_nodal_connec->getPointer();
6160 const int *connI=_nodal_connec_index->getConstPointer();
6161 const double *coordsPtr=_coords->getConstPointer();
6162 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6163 for(int i=0;i<nbOfCells;i++)
6165 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6168 case INTERP_KERNEL::NORM_TETRA4:
6170 if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6172 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6173 ret->pushBackSilent(i);
6177 case INTERP_KERNEL::NORM_PYRA5:
6179 if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6181 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6182 ret->pushBackSilent(i);
6186 case INTERP_KERNEL::NORM_PENTA6:
6187 case INTERP_KERNEL::NORM_HEXA8:
6188 case INTERP_KERNEL::NORM_HEXGP12:
6190 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6192 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6193 ret->pushBackSilent(i);
6197 case INTERP_KERNEL::NORM_POLYHED:
6199 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6201 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6202 ret->pushBackSilent(i);
6207 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 !");
6215 * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6216 * If it is not the case an exception will be thrown.
6217 * This method is fast because the first cell of \a this is used to compute the plane.
6218 * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6219 * \param pos output of size at least 3 used to store a point owned of searched plane.
6221 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6223 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6224 throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6225 const int *conn=_nodal_connec->getConstPointer();
6226 const int *connI=_nodal_connec_index->getConstPointer();
6227 const double *coordsPtr=_coords->getConstPointer();
6228 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6229 std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6233 * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6234 * cells. Currently cells of the following types are treated:
6235 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6236 * For a cell of other type an exception is thrown.
6237 * Space dimension of a 2D mesh can be either 2 or 3.
6238 * The Edge Ratio of a cell \f$t\f$ is:
6239 * \f$\frac{|t|_\infty}{|t|_0}\f$,
6240 * where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6241 * the smallest edge lengths of \f$t\f$.
6242 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6243 * cells and one time, lying on \a this mesh. The caller is to delete this
6244 * field using decrRef() as it is no more needed.
6245 * \throw If the coordinates array is not set.
6246 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6247 * \throw If the connectivity data array has more than one component.
6248 * \throw If the connectivity data array has a named component.
6249 * \throw If the connectivity index data array has more than one component.
6250 * \throw If the connectivity index data array has a named component.
6251 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6252 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6253 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6255 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6258 int spaceDim=getSpaceDimension();
6259 int meshDim=getMeshDimension();
6260 if(spaceDim!=2 && spaceDim!=3)
6261 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6262 if(meshDim!=2 && meshDim!=3)
6263 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6264 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6266 int nbOfCells=getNumberOfCells();
6267 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6268 arr->alloc(nbOfCells,1);
6269 double *pt=arr->getPointer();
6270 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6271 const int *conn=_nodal_connec->getConstPointer();
6272 const int *connI=_nodal_connec_index->getConstPointer();
6273 const double *coo=_coords->getConstPointer();
6275 for(int i=0;i<nbOfCells;i++,pt++)
6277 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6280 case INTERP_KERNEL::NORM_TRI3:
6282 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6283 *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6286 case INTERP_KERNEL::NORM_QUAD4:
6288 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6289 *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6292 case INTERP_KERNEL::NORM_TETRA4:
6294 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6295 *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6299 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6301 conn+=connI[i+1]-connI[i];
6303 ret->setName("EdgeRatio");
6304 ret->synchronizeTimeWithSupport();
6309 * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6310 * cells. Currently cells of the following types are treated:
6311 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6312 * For a cell of other type an exception is thrown.
6313 * Space dimension of a 2D mesh can be either 2 or 3.
6314 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6315 * cells and one time, lying on \a this mesh. The caller is to delete this
6316 * field using decrRef() as it is no more needed.
6317 * \throw If the coordinates array is not set.
6318 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6319 * \throw If the connectivity data array has more than one component.
6320 * \throw If the connectivity data array has a named component.
6321 * \throw If the connectivity index data array has more than one component.
6322 * \throw If the connectivity index data array has a named component.
6323 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6324 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6325 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6327 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6330 int spaceDim=getSpaceDimension();
6331 int meshDim=getMeshDimension();
6332 if(spaceDim!=2 && spaceDim!=3)
6333 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6334 if(meshDim!=2 && meshDim!=3)
6335 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6336 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6338 int nbOfCells=getNumberOfCells();
6339 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6340 arr->alloc(nbOfCells,1);
6341 double *pt=arr->getPointer();
6342 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6343 const int *conn=_nodal_connec->getConstPointer();
6344 const int *connI=_nodal_connec_index->getConstPointer();
6345 const double *coo=_coords->getConstPointer();
6347 for(int i=0;i<nbOfCells;i++,pt++)
6349 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6352 case INTERP_KERNEL::NORM_TRI3:
6354 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6355 *pt=INTERP_KERNEL::triAspectRatio(tmp);
6358 case INTERP_KERNEL::NORM_QUAD4:
6360 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6361 *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6364 case INTERP_KERNEL::NORM_TETRA4:
6366 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6367 *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6371 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6373 conn+=connI[i+1]-connI[i];
6375 ret->setName("AspectRatio");
6376 ret->synchronizeTimeWithSupport();
6381 * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6382 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6383 * treated: INTERP_KERNEL::NORM_QUAD4.
6384 * For a cell of other type an exception is thrown.
6385 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6386 * cells and one time, lying on \a this mesh. The caller is to delete this
6387 * field using decrRef() as it is no more needed.
6388 * \throw If the coordinates array is not set.
6389 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6390 * \throw If the connectivity data array has more than one component.
6391 * \throw If the connectivity data array has a named component.
6392 * \throw If the connectivity index data array has more than one component.
6393 * \throw If the connectivity index data array has a named component.
6394 * \throw If \a this->getMeshDimension() != 2.
6395 * \throw If \a this->getSpaceDimension() != 3.
6396 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6398 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6401 int spaceDim=getSpaceDimension();
6402 int meshDim=getMeshDimension();
6404 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6406 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6407 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6409 int nbOfCells=getNumberOfCells();
6410 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6411 arr->alloc(nbOfCells,1);
6412 double *pt=arr->getPointer();
6413 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6414 const int *conn=_nodal_connec->getConstPointer();
6415 const int *connI=_nodal_connec_index->getConstPointer();
6416 const double *coo=_coords->getConstPointer();
6418 for(int i=0;i<nbOfCells;i++,pt++)
6420 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6423 case INTERP_KERNEL::NORM_QUAD4:
6425 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6426 *pt=INTERP_KERNEL::quadWarp(tmp);
6430 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6432 conn+=connI[i+1]-connI[i];
6434 ret->setName("Warp");
6435 ret->synchronizeTimeWithSupport();
6441 * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6442 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6443 * treated: INTERP_KERNEL::NORM_QUAD4.
6444 * For a cell of other type an exception is thrown.
6445 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6446 * cells and one time, lying on \a this mesh. The caller is to delete this
6447 * field using decrRef() as it is no more needed.
6448 * \throw If the coordinates array is not set.
6449 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6450 * \throw If the connectivity data array has more than one component.
6451 * \throw If the connectivity data array has a named component.
6452 * \throw If the connectivity index data array has more than one component.
6453 * \throw If the connectivity index data array has a named component.
6454 * \throw If \a this->getMeshDimension() != 2.
6455 * \throw If \a this->getSpaceDimension() != 3.
6456 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6458 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6461 int spaceDim=getSpaceDimension();
6462 int meshDim=getMeshDimension();
6464 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6466 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6467 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6469 int nbOfCells=getNumberOfCells();
6470 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6471 arr->alloc(nbOfCells,1);
6472 double *pt=arr->getPointer();
6473 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6474 const int *conn=_nodal_connec->getConstPointer();
6475 const int *connI=_nodal_connec_index->getConstPointer();
6476 const double *coo=_coords->getConstPointer();
6478 for(int i=0;i<nbOfCells;i++,pt++)
6480 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6483 case INTERP_KERNEL::NORM_QUAD4:
6485 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6486 *pt=INTERP_KERNEL::quadSkew(tmp);
6490 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6492 conn+=connI[i+1]-connI[i];
6494 ret->setName("Skew");
6495 ret->synchronizeTimeWithSupport();
6500 * This method aggregate the bbox of each cell and put it into bbox parameter.
6502 * \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)
6503 * For all other cases this input parameter is ignored.
6504 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6506 * \throw If \a this is not fully set (coordinates and connectivity).
6507 * \throw If a cell in \a this has no valid nodeId.
6508 * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6510 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6512 int mDim(getMeshDimension()),sDim(getSpaceDimension());
6513 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.
6514 return getBoundingBoxForBBTreeFast();
6515 if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6517 bool presenceOfQuadratic(false);
6518 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6520 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6521 if(cm.isQuadratic())
6522 presenceOfQuadratic=true;
6524 if(!presenceOfQuadratic)
6525 return getBoundingBoxForBBTreeFast();
6526 if(mDim==2 && sDim==2)
6527 return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6529 return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6531 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) !");
6535 * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6536 * So meshes having quadratic cells the computed bounding boxes can be invalid !
6538 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6540 * \throw If \a this is not fully set (coordinates and connectivity).
6541 * \throw If a cell in \a this has no valid nodeId.
6543 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6545 checkFullyDefined();
6546 int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6547 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6548 double *bbox(ret->getPointer());
6549 for(int i=0;i<nbOfCells*spaceDim;i++)
6551 bbox[2*i]=std::numeric_limits<double>::max();
6552 bbox[2*i+1]=-std::numeric_limits<double>::max();
6554 const double *coordsPtr(_coords->getConstPointer());
6555 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6556 for(int i=0;i<nbOfCells;i++)
6558 int offset=connI[i]+1;
6559 int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6560 for(int j=0;j<nbOfNodesForCell;j++)
6562 int nodeId=conn[offset+j];
6563 if(nodeId>=0 && nodeId<nbOfNodes)
6565 for(int k=0;k<spaceDim;k++)
6567 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6568 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6575 std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6576 throw INTERP_KERNEL::Exception(oss.str().c_str());
6583 * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6584 * useful for 2D meshes having quadratic cells
6585 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6586 * the two extremities of the arc of circle).
6588 * \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)
6589 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6590 * \throw If \a this is not fully defined.
6591 * \throw If \a this is not a mesh with meshDimension equal to 2.
6592 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6593 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6595 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6597 checkFullyDefined();
6598 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6599 if(spaceDim!=2 || mDim!=2)
6600 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!");
6601 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6602 double *bbox(ret->getPointer());
6603 const double *coords(_coords->getConstPointer());
6604 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6605 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6607 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6608 int sz(connI[1]-connI[0]-1);
6609 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6610 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6611 INTERP_KERNEL::QuadraticPolygon *pol(0);
6612 for(int j=0;j<sz;j++)
6614 int nodeId(conn[*connI+1+j]);
6615 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6617 if(!cm.isQuadratic())
6618 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6620 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6621 INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6622 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax();
6628 * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6629 * useful for 2D meshes having quadratic cells
6630 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6631 * the two extremities of the arc of circle).
6633 * \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)
6634 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6635 * \throw If \a this is not fully defined.
6636 * \throw If \a this is not a mesh with meshDimension equal to 1.
6637 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6638 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6640 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6642 checkFullyDefined();
6643 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6644 if(spaceDim!=2 || mDim!=1)
6645 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!");
6646 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6647 double *bbox(ret->getPointer());
6648 const double *coords(_coords->getConstPointer());
6649 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6650 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6652 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6653 int sz(connI[1]-connI[0]-1);
6654 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6655 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6656 INTERP_KERNEL::Edge *edge(0);
6657 for(int j=0;j<sz;j++)
6659 int nodeId(conn[*connI+1+j]);
6660 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6662 if(!cm.isQuadratic())
6663 edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6665 edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6666 const INTERP_KERNEL::Bounds& b(edge->getBounds());
6667 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6674 namespace ParaMEDMEMImpl
6679 ConnReader(const int *c, int val):_conn(c),_val(val) { }
6680 bool operator() (const int& pos) { return _conn[pos]!=_val; }
6689 ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6690 bool operator() (const int& pos) { return _conn[pos]==_val; }
6700 * This method expects that \a this is sorted by types. If not an exception will be thrown.
6701 * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6702 * \a this is composed in cell types.
6703 * The returned array is of size 3*n where n is the number of different types present in \a this.
6704 * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here.
6705 * This parameter is kept only for compatibility with other methode listed above.
6707 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6709 checkConnectivityFullyDefined();
6710 const int *conn=_nodal_connec->getConstPointer();
6711 const int *connI=_nodal_connec_index->getConstPointer();
6712 const int *work=connI;
6713 int nbOfCells=getNumberOfCells();
6714 std::size_t n=getAllGeoTypes().size();
6715 std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6716 std::set<INTERP_KERNEL::NormalizedCellType> types;
6717 for(std::size_t i=0;work!=connI+nbOfCells;i++)
6719 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6720 if(types.find(typ)!=types.end())
6722 std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6723 oss << " is not contiguous !";
6724 throw INTERP_KERNEL::Exception(oss.str().c_str());
6728 const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6729 ret[3*i+1]=(int)std::distance(work,work2);
6736 * This method is used to check that this has contiguous cell type in same order than described in \a code.
6737 * only for types cell, type node is not managed.
6738 * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6739 * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6740 * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6741 * If 2 or more same geometric type is in \a code and exception is thrown too.
6743 * This method firstly checks
6744 * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6745 * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6746 * an exception is thrown too.
6748 * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6749 * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown
6750 * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6752 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6755 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6756 std::size_t sz=code.size();
6759 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6760 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6762 bool isNoPflUsed=true;
6763 for(std::size_t i=0;i<n;i++)
6764 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6766 types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6768 if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6769 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6770 isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6773 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6776 if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6777 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6778 if(types.size()==_types.size())
6781 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6783 int *retPtr=ret->getPointer();
6784 const int *connI=_nodal_connec_index->getConstPointer();
6785 const int *conn=_nodal_connec->getConstPointer();
6786 int nbOfCells=getNumberOfCells();
6789 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6791 i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6792 int offset=(int)std::distance(connI,i);
6793 const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6794 int nbOfCellsOfCurType=(int)std::distance(i,j);
6795 if(code[3*kk+2]==-1)
6796 for(int k=0;k<nbOfCellsOfCurType;k++)
6800 int idInIdsPerType=code[3*kk+2];
6801 if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6803 const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6806 zePfl->checkAllocated();
6807 if(zePfl->getNumberOfComponents()==1)
6809 for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6811 if(*k>=0 && *k<nbOfCellsOfCurType)
6812 *retPtr=(*k)+offset;
6815 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6816 oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6817 throw INTERP_KERNEL::Exception(oss.str().c_str());
6822 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6825 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6829 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6830 oss << " should be in [0," << idsPerType.size() << ") !";
6831 throw INTERP_KERNEL::Exception(oss.str().c_str());
6840 * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6841 * 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.
6842 * 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.
6843 * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6845 * \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.
6846 * \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,
6847 * \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6848 * \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.
6849 * This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6850 * \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
6852 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6855 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6856 if(profile->getNumberOfComponents()!=1)
6857 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6858 checkConnectivityFullyDefined();
6859 const int *conn=_nodal_connec->getConstPointer();
6860 const int *connI=_nodal_connec_index->getConstPointer();
6861 int nbOfCells=getNumberOfCells();
6862 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6863 std::vector<int> typeRangeVals(1);
6864 for(const int *i=connI;i!=connI+nbOfCells;)
6866 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6867 if(std::find(types.begin(),types.end(),curType)!=types.end())
6869 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6871 types.push_back(curType);
6872 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6873 typeRangeVals.push_back((int)std::distance(connI,i));
6876 DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6877 profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6878 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6879 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6880 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6882 int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6883 code.resize(3*nbOfCastsFinal);
6884 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6885 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6886 for(int i=0;i<nbOfCastsFinal;i++)
6888 int castId=castsPresent->getIJ(i,0);
6889 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6890 idsInPflPerType2.push_back(tmp3);
6891 code[3*i]=(int)types[castId];
6892 code[3*i+1]=tmp3->getNumberOfTuples();
6893 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6894 if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6896 tmp4->copyStringInfoFrom(*profile);
6897 idsPerType2.push_back(tmp4);
6898 code[3*i+2]=(int)idsPerType2.size()-1;
6905 std::size_t sz2=idsInPflPerType2.size();
6906 idsInPflPerType.resize(sz2);
6907 for(std::size_t i=0;i<sz2;i++)
6909 DataArrayInt *locDa=idsInPflPerType2[i];
6911 idsInPflPerType[i]=locDa;
6913 std::size_t sz=idsPerType2.size();
6914 idsPerType.resize(sz);
6915 for(std::size_t i=0;i<sz;i++)
6917 DataArrayInt *locDa=idsPerType2[i];
6919 idsPerType[i]=locDa;
6924 * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6925 * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6926 * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6927 * 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.
6929 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
6931 checkFullyDefined();
6932 nM1LevMesh->checkFullyDefined();
6933 if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6934 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6935 if(_coords!=nM1LevMesh->getCoords())
6936 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6937 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6938 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6939 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6940 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6941 desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6942 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6943 tmp->setConnectivity(tmp0,tmp1);
6944 tmp->renumberCells(ret0->getConstPointer(),false);
6945 revDesc=tmp->getNodalConnectivity();
6946 revDescIndx=tmp->getNodalConnectivityIndex();
6947 DataArrayInt *ret=0;
6948 if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6951 ret->getMaxValue(tmp2);
6953 std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6954 throw INTERP_KERNEL::Exception(oss.str().c_str());
6959 revDescIndx->incrRef();
6962 meshnM1Old2New=ret0;
6967 * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6968 * necessary for writing the mesh to MED file. Additionally returns a permutation array
6969 * in "Old to New" mode.
6970 * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6971 * this array using decrRef() as it is no more needed.
6972 * \throw If the nodal connectivity of cells is not defined.
6974 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
6976 checkConnectivityFullyDefined();
6977 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6978 renumberCells(ret->getConstPointer(),false);
6983 * This methods checks that cells are sorted by their types.
6984 * This method makes asumption (no check) that connectivity is correctly set before calling.
6986 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6988 checkFullyDefined();
6989 const int *conn=_nodal_connec->getConstPointer();
6990 const int *connI=_nodal_connec_index->getConstPointer();
6991 int nbOfCells=getNumberOfCells();
6992 std::set<INTERP_KERNEL::NormalizedCellType> types;
6993 for(const int *i=connI;i!=connI+nbOfCells;)
6995 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6996 if(types.find(curType)!=types.end())
6998 types.insert(curType);
6999 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7005 * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
7006 * The geometric type order is specified by MED file.
7008 * \sa MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
7010 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
7012 return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7016 * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
7017 * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
7018 * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
7019 * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
7021 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7023 checkFullyDefined();
7024 const int *conn=_nodal_connec->getConstPointer();
7025 const int *connI=_nodal_connec_index->getConstPointer();
7026 int nbOfCells=getNumberOfCells();
7030 std::set<INTERP_KERNEL::NormalizedCellType> sg;
7031 for(const int *i=connI;i!=connI+nbOfCells;)
7033 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7034 const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
7035 if(isTypeExists!=orderEnd)
7037 int pos=(int)std::distance(orderBg,isTypeExists);
7041 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7045 if(sg.find(curType)==sg.end())
7047 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7058 * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
7059 * 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
7060 * 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'.
7062 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
7064 checkConnectivityFullyDefined();
7065 int nbOfCells=getNumberOfCells();
7066 const int *conn=_nodal_connec->getConstPointer();
7067 const int *connI=_nodal_connec_index->getConstPointer();
7068 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
7069 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
7070 tmpa->alloc(nbOfCells,1);
7071 tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
7072 tmpb->fillWithZero();
7073 int *tmp=tmpa->getPointer();
7074 int *tmp2=tmpb->getPointer();
7075 for(const int *i=connI;i!=connI+nbOfCells;i++)
7077 const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
7080 int pos=(int)std::distance(orderBg,where);
7082 tmp[std::distance(connI,i)]=pos;
7086 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
7087 std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
7088 oss << " has a type " << cm.getRepr() << " not in input array of type !";
7089 throw INTERP_KERNEL::Exception(oss.str().c_str());
7092 nbPerType=tmpb.retn();
7097 * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7099 * \return a new object containing the old to new correspondance.
7101 * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7103 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7105 return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7109 * 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.
7110 * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7111 * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7112 * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7114 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7116 DataArrayInt *nbPerType=0;
7117 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7118 nbPerType->decrRef();
7119 return tmpa->buildPermArrPerLevel();
7123 * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7124 * The number of cells remains unchanged after the call of this method.
7125 * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7126 * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7128 * \return the array giving the correspondance old to new.
7130 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7132 checkFullyDefined();
7134 const int *conn=_nodal_connec->getConstPointer();
7135 const int *connI=_nodal_connec_index->getConstPointer();
7136 int nbOfCells=getNumberOfCells();
7137 std::vector<INTERP_KERNEL::NormalizedCellType> types;
7138 for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7139 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7141 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7142 types.push_back(curType);
7143 for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7145 DataArrayInt *ret=DataArrayInt::New();
7146 ret->alloc(nbOfCells,1);
7147 int *retPtr=ret->getPointer();
7148 std::fill(retPtr,retPtr+nbOfCells,-1);
7150 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7152 for(const int *i=connI;i!=connI+nbOfCells;i++)
7153 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7154 retPtr[std::distance(connI,i)]=newCellId++;
7156 renumberCells(retPtr,false);
7161 * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7162 * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7163 * This method makes asumption that connectivity is correctly set before calling.
7165 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7167 checkConnectivityFullyDefined();
7168 const int *conn=_nodal_connec->getConstPointer();
7169 const int *connI=_nodal_connec_index->getConstPointer();
7170 int nbOfCells=getNumberOfCells();
7171 std::vector<MEDCouplingUMesh *> ret;
7172 for(const int *i=connI;i!=connI+nbOfCells;)
7174 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7175 int beginCellId=(int)std::distance(connI,i);
7176 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7177 int endCellId=(int)std::distance(connI,i);
7178 int sz=endCellId-beginCellId;
7179 int *cells=new int[sz];
7180 for(int j=0;j<sz;j++)
7181 cells[j]=beginCellId+j;
7182 MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7190 * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7191 * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7192 * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7194 * \return a newly allocated instance, that the caller must manage.
7195 * \throw If \a this contains more than one geometric type.
7196 * \throw If the nodal connectivity of \a this is not fully defined.
7197 * \throw If the internal data is not coherent.
7199 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7201 checkConnectivityFullyDefined();
7202 if(_types.size()!=1)
7203 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7204 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7205 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7206 ret->setCoords(getCoords());
7207 MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7210 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7211 retC->setNodalConnectivity(c);
7215 MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7217 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7218 DataArrayInt *c=0,*ci=0;
7219 convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7220 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7221 retD->setNodalConnectivity(cs,cis);
7226 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7228 checkConnectivityFullyDefined();
7229 if(_types.size()!=1)
7230 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7231 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7232 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7235 std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7236 oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7237 throw INTERP_KERNEL::Exception(oss.str().c_str());
7239 int nbCells=getNumberOfCells();
7241 int nbNodesPerCell=(int)cm.getNumberOfNodes();
7242 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7243 int *outPtr=connOut->getPointer();
7244 const int *conn=_nodal_connec->begin();
7245 const int *connI=_nodal_connec_index->begin();
7247 for(int i=0;i<nbCells;i++,connI++)
7249 if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7250 outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7253 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 << ") !";
7254 throw INTERP_KERNEL::Exception(oss.str().c_str());
7257 return connOut.retn();
7260 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7262 static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7263 checkConnectivityFullyDefined();
7264 if(_types.size()!=1)
7265 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7266 int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7268 throw INTERP_KERNEL::Exception(msg0);
7269 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7270 c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7271 int *cp(c->getPointer()),*cip(ci->getPointer());
7272 const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7274 for(int i=0;i<nbCells;i++,cip++,incip++)
7276 int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7277 int delta(stop-strt);
7280 if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7281 cp=std::copy(incp+strt,incp+stop,cp);
7283 throw INTERP_KERNEL::Exception(msg0);
7286 throw INTERP_KERNEL::Exception(msg0);
7287 cip[1]=cip[0]+delta;
7289 nodalConn=c.retn(); nodalConnIndex=ci.retn();
7293 * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7294 * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7295 * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7296 * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7297 * are not used here to avoid the build of big permutation array.
7299 * \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
7300 * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7301 * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7302 * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7303 * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7304 * output array gives for each chunck of same type the corresponding mesh id in \b ms.
7305 * \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
7306 * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7308 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7309 DataArrayInt *&szOfCellGrpOfSameType,
7310 DataArrayInt *&idInMsOfCellGrpOfSameType)
7312 std::vector<const MEDCouplingUMesh *> ms2;
7313 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7316 (*it)->checkConnectivityFullyDefined();
7320 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7321 const DataArrayDouble *refCoo=ms2[0]->getCoords();
7322 int meshDim=ms2[0]->getMeshDimension();
7323 std::vector<const MEDCouplingUMesh *> m1ssm;
7324 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7326 std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7327 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7329 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7330 ret1->alloc(0,1); ret2->alloc(0,1);
7331 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7333 if(meshDim!=(*it)->getMeshDimension())
7334 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7335 if(refCoo!=(*it)->getCoords())
7336 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7337 std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7338 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7339 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7340 for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7342 MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7343 m1ssmSingleAuto.push_back(singleCell);
7344 m1ssmSingle.push_back(singleCell);
7345 ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7348 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7349 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7350 std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7351 for(std::size_t i=0;i<m1ssm.size();i++)
7352 m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7353 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7354 szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7355 idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7360 * This method returns a newly created DataArrayInt instance.
7361 * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7363 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7365 checkFullyDefined();
7366 const int *conn=_nodal_connec->getConstPointer();
7367 const int *connIndex=_nodal_connec_index->getConstPointer();
7368 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7369 for(const int *w=begin;w!=end;w++)
7370 if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7371 ret->pushBackSilent(*w);
7376 * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7377 * are in [0:getNumberOfCells())
7379 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7381 checkFullyDefined();
7382 const int *conn=_nodal_connec->getConstPointer();
7383 const int *connI=_nodal_connec_index->getConstPointer();
7384 int nbOfCells=getNumberOfCells();
7385 std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7386 int *tmp=new int[nbOfCells];
7387 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7390 for(const int *i=connI;i!=connI+nbOfCells;i++)
7391 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7392 tmp[std::distance(connI,i)]=j++;
7394 DataArrayInt *ret=DataArrayInt::New();
7395 ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7396 ret->copyStringInfoFrom(*da);
7397 int *retPtr=ret->getPointer();
7398 const int *daPtr=da->getConstPointer();
7399 int nbOfElems=da->getNbOfElems();
7400 for(int k=0;k<nbOfElems;k++)
7401 retPtr[k]=tmp[daPtr[k]];
7407 * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7408 * This method \b works \b for mesh sorted by type.
7409 * cells whose ids is in 'idsPerGeoType' array.
7410 * This method conserves coords and name of mesh.
7412 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7414 std::vector<int> code=getDistributionOfTypes();
7415 std::size_t nOfTypesInThis=code.size()/3;
7416 int sz=0,szOfType=0;
7417 for(std::size_t i=0;i<nOfTypesInThis;i++)
7422 szOfType=code[3*i+1];
7424 for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7425 if(*work<0 || *work>=szOfType)
7427 std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7428 oss << ". It should be in [0," << szOfType << ") !";
7429 throw INTERP_KERNEL::Exception(oss.str().c_str());
7431 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7432 int *idsPtr=idsTokeep->getPointer();
7434 for(std::size_t i=0;i<nOfTypesInThis;i++)
7437 for(int j=0;j<code[3*i+1];j++)
7440 idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7441 offset+=code[3*i+1];
7443 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7444 ret->copyTinyInfoFrom(this);
7449 * This method returns a vector of size 'this->getNumberOfCells()'.
7450 * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7452 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7454 int ncell=getNumberOfCells();
7455 std::vector<bool> ret(ncell);
7456 const int *cI=getNodalConnectivityIndex()->getConstPointer();
7457 const int *c=getNodalConnectivity()->getConstPointer();
7458 for(int i=0;i<ncell;i++)
7460 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7461 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7462 ret[i]=cm.isQuadratic();
7468 * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7470 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7472 if(other->getType()!=UNSTRUCTURED)
7473 throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7474 const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7475 return MergeUMeshes(this,otherC);
7479 * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7480 * computed by averaging coordinates of cell nodes, so this method is not a right
7481 * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7482 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7483 * this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7484 * components. The caller is to delete this array using decrRef() as it is
7486 * \throw If the coordinates array is not set.
7487 * \throw If the nodal connectivity of cells is not defined.
7488 * \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7490 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7492 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7493 int spaceDim=getSpaceDimension();
7494 int nbOfCells=getNumberOfCells();
7495 ret->alloc(nbOfCells,spaceDim);
7496 ret->copyStringInfoFrom(*getCoords());
7497 double *ptToFill=ret->getPointer();
7498 const int *nodal=_nodal_connec->getConstPointer();
7499 const int *nodalI=_nodal_connec_index->getConstPointer();
7500 const double *coor=_coords->getConstPointer();
7501 for(int i=0;i<nbOfCells;i++)
7503 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7504 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7511 * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7512 * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the
7514 * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned
7515 * DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7517 * \sa MEDCouplingUMesh::getBarycenterAndOwner
7518 * \throw If \a this is not fully defined (coordinates and connectivity)
7519 * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7521 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7523 checkFullyDefined();
7524 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7525 int spaceDim=getSpaceDimension();
7526 int nbOfCells=getNumberOfCells();
7527 int nbOfNodes=getNumberOfNodes();
7528 ret->alloc(nbOfCells,spaceDim);
7529 double *ptToFill=ret->getPointer();
7530 const int *nodal=_nodal_connec->getConstPointer();
7531 const int *nodalI=_nodal_connec_index->getConstPointer();
7532 const double *coor=_coords->getConstPointer();
7533 for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7535 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7536 std::fill(ptToFill,ptToFill+spaceDim,0.);
7537 if(type!=INTERP_KERNEL::NORM_POLYHED)
7539 for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7541 if(*conn>=0 && *conn<nbOfNodes)
7542 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7545 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," << nbOfNodes << ") !";
7546 throw INTERP_KERNEL::Exception(oss.str().c_str());
7549 int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7550 if(nbOfNodesInCell>0)
7551 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7554 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7555 throw INTERP_KERNEL::Exception(oss.str().c_str());
7560 std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7562 for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7564 if(*it>=0 && *it<nbOfNodes)
7565 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7568 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," << nbOfNodes << ") !";
7569 throw INTERP_KERNEL::Exception(oss.str().c_str());
7573 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7576 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7577 throw INTERP_KERNEL::Exception(oss.str().c_str());
7585 * Returns a new DataArrayDouble holding barycenters of specified cells. The
7586 * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7587 * are specified via an array of cell ids.
7588 * \warning Validity of the specified cell ids is not checked!
7589 * Valid range is [ 0, \a this->getNumberOfCells() ).
7590 * \param [in] begin - an array of cell ids of interest.
7591 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7592 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7593 * end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7594 * caller is to delete this array using decrRef() as it is no more needed.
7595 * \throw If the coordinates array is not set.
7596 * \throw If the nodal connectivity of cells is not defined.
7598 * \if ENABLE_EXAMPLES
7599 * \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7600 * \ref py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7603 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7605 DataArrayDouble *ret=DataArrayDouble::New();
7606 int spaceDim=getSpaceDimension();
7607 int nbOfTuple=(int)std::distance(begin,end);
7608 ret->alloc(nbOfTuple,spaceDim);
7609 double *ptToFill=ret->getPointer();
7610 double *tmp=new double[spaceDim];
7611 const int *nodal=_nodal_connec->getConstPointer();
7612 const int *nodalI=_nodal_connec_index->getConstPointer();
7613 const double *coor=_coords->getConstPointer();
7614 for(const int *w=begin;w!=end;w++)
7616 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7617 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7625 * 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".
7626 * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7627 * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7628 * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7629 * This method is useful to detect 2D cells in 3D space that are not coplanar.
7631 * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7632 * \throw If spaceDim!=3 or meshDim!=2.
7633 * \throw If connectivity of \a this is invalid.
7634 * \throw If connectivity of a cell in \a this points to an invalid node.
7636 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7638 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7639 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7640 if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7641 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7642 ret->alloc(nbOfCells,4);
7643 double *retPtr(ret->getPointer());
7644 const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7645 const double *coor(_coords->begin());
7646 for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7648 double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7649 if(nodalI[1]-nodalI[0]>=3)
7651 for(int j=0;j<3;j++)
7653 int nodeId(nodal[nodalI[0]+1+j]);
7654 if(nodeId>=0 && nodeId<nbOfNodes)
7655 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7658 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7659 throw INTERP_KERNEL::Exception(oss.str().c_str());
7665 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7666 throw INTERP_KERNEL::Exception(oss.str().c_str());
7668 INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7669 retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7675 * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7678 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7681 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7682 da->checkAllocated();
7683 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7685 int nbOfTuples=da->getNumberOfTuples();
7686 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7687 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7688 c->alloc(2*nbOfTuples,1);
7689 cI->alloc(nbOfTuples+1,1);
7690 int *cp=c->getPointer();
7691 int *cip=cI->getPointer();
7693 for(int i=0;i<nbOfTuples;i++)
7695 *cp++=INTERP_KERNEL::NORM_POINT1;
7699 ret->setConnectivity(c,cI,true);
7703 * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7704 * Cells and nodes of
7705 * the first mesh precede cells and nodes of the second mesh within the result mesh.
7706 * \param [in] mesh1 - the first mesh.
7707 * \param [in] mesh2 - the second mesh.
7708 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7709 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7710 * is no more needed.
7711 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7712 * \throw If the coordinates array is not set in none of the meshes.
7713 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7714 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7716 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7718 std::vector<const MEDCouplingUMesh *> tmp(2);
7719 tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7720 return MergeUMeshes(tmp);
7724 * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7725 * Cells and nodes of
7726 * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7727 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7728 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7729 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7730 * is no more needed.
7731 * \throw If \a a.size() == 0.
7732 * \throw If \a a[ *i* ] == NULL.
7733 * \throw If the coordinates array is not set in none of the meshes.
7734 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7735 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7737 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7739 std::size_t sz=a.size();
7741 return MergeUMeshesLL(a);
7742 for(std::size_t ii=0;ii<sz;ii++)
7745 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7746 throw INTERP_KERNEL::Exception(oss.str().c_str());
7748 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7749 std::vector< const MEDCouplingUMesh * > aa(sz);
7751 for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7753 const MEDCouplingUMesh *cur=a[i];
7754 const DataArrayDouble *coo=cur->getCoords();
7756 spaceDim=coo->getNumberOfComponents();
7759 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7760 for(std::size_t i=0;i<sz;i++)
7762 bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7765 return MergeUMeshesLL(aa);
7770 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7773 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7774 std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7775 int meshDim=(*it)->getMeshDimension();
7776 int nbOfCells=(*it)->getNumberOfCells();
7777 int meshLgth=(*it++)->getMeshLength();
7778 for(;it!=a.end();it++)
7780 if(meshDim!=(*it)->getMeshDimension())
7781 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7782 nbOfCells+=(*it)->getNumberOfCells();
7783 meshLgth+=(*it)->getMeshLength();
7785 std::vector<const MEDCouplingPointSet *> aps(a.size());
7786 std::copy(a.begin(),a.end(),aps.begin());
7787 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7788 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7789 ret->setCoords(pts);
7790 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7791 c->alloc(meshLgth,1);
7792 int *cPtr=c->getPointer();
7793 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7794 cI->alloc(nbOfCells+1,1);
7795 int *cIPtr=cI->getPointer();
7799 for(it=a.begin();it!=a.end();it++)
7801 int curNbOfCell=(*it)->getNumberOfCells();
7802 const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7803 const int *curC=(*it)->_nodal_connec->getConstPointer();
7804 cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7805 for(int j=0;j<curNbOfCell;j++)
7807 const int *src=curC+curCI[j];
7809 for(;src!=curC+curCI[j+1];src++,cPtr++)
7817 offset+=curCI[curNbOfCell];
7818 offset2+=(*it)->getNumberOfNodes();
7821 ret->setConnectivity(c,cI,true);
7828 * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7829 * dimension and sharing the node coordinates array.
7830 * All cells of the first mesh precede all cells of the second mesh
7831 * within the result mesh.
7832 * \param [in] mesh1 - the first mesh.
7833 * \param [in] mesh2 - the second mesh.
7834 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7835 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7836 * is no more needed.
7837 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7838 * \throw If the meshes do not share the node coordinates array.
7839 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7840 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7842 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7844 std::vector<const MEDCouplingUMesh *> tmp(2);
7845 tmp[0]=mesh1; tmp[1]=mesh2;
7846 return MergeUMeshesOnSameCoords(tmp);
7850 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7851 * dimension and sharing the node coordinates array.
7852 * All cells of the *i*-th mesh precede all cells of the
7853 * (*i*+1)-th mesh within the result mesh.
7854 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7855 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7856 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7857 * is no more needed.
7858 * \throw If \a a.size() == 0.
7859 * \throw If \a a[ *i* ] == NULL.
7860 * \throw If the meshes do not share the node coordinates array.
7861 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7862 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7864 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7867 throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7868 for(std::size_t ii=0;ii<meshes.size();ii++)
7871 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7872 throw INTERP_KERNEL::Exception(oss.str().c_str());
7874 const DataArrayDouble *coords=meshes.front()->getCoords();
7875 int meshDim=meshes.front()->getMeshDimension();
7876 std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7878 int meshIndexLgth=0;
7879 for(;iter!=meshes.end();iter++)
7881 if(coords!=(*iter)->getCoords())
7882 throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7883 if(meshDim!=(*iter)->getMeshDimension())
7884 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7885 meshLgth+=(*iter)->getMeshLength();
7886 meshIndexLgth+=(*iter)->getNumberOfCells();
7888 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7889 nodal->alloc(meshLgth,1);
7890 int *nodalPtr=nodal->getPointer();
7891 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7892 nodalIndex->alloc(meshIndexLgth+1,1);
7893 int *nodalIndexPtr=nodalIndex->getPointer();
7895 for(iter=meshes.begin();iter!=meshes.end();iter++)
7897 const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7898 const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7899 int nbOfCells=(*iter)->getNumberOfCells();
7900 int meshLgth2=(*iter)->getMeshLength();
7901 nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7902 if(iter!=meshes.begin())
7903 nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7905 nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7908 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7909 ret->setName("merge");
7910 ret->setMeshDimension(meshDim);
7911 ret->setConnectivity(nodal,nodalIndex,true);
7912 ret->setCoords(coords);
7917 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7918 * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7919 * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7920 * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7921 * New" mode are returned for each input mesh.
7922 * \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7923 * \param [in] compType - specifies a cell comparison technique. For meaning of its
7924 * valid values [0,1,2], see zipConnectivityTraducer().
7925 * \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7926 * meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7927 * mesh. The caller is to delete each of the arrays using decrRef() as it is
7929 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7930 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7931 * is no more needed.
7932 * \throw If \a meshes.size() == 0.
7933 * \throw If \a meshes[ *i* ] == NULL.
7934 * \throw If the meshes do not share the node coordinates array.
7935 * \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7936 * \throw If the \a meshes are of different dimension (getMeshDimension()).
7937 * \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7938 * \throw If the nodal connectivity any of \a meshes includes an invalid id.
7940 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7942 //All checks are delegated to MergeUMeshesOnSameCoords
7943 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7944 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7945 corr.resize(meshes.size());
7946 std::size_t nbOfMeshes=meshes.size();
7948 const int *o2nPtr=o2n->getConstPointer();
7949 for(std::size_t i=0;i<nbOfMeshes;i++)
7951 DataArrayInt *tmp=DataArrayInt::New();
7952 int curNbOfCells=meshes[i]->getNumberOfCells();
7953 tmp->alloc(curNbOfCells,1);
7954 std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7955 offset+=curNbOfCells;
7956 tmp->setName(meshes[i]->getName());
7963 * Makes all given meshes share the nodal connectivity array. The common connectivity
7964 * array is created by concatenating the connectivity arrays of all given meshes. All
7965 * the given meshes must be of the same space dimension but dimension of cells **can
7966 * differ**. This method is particulary useful in MEDLoader context to build a \ref
7967 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7968 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7969 * \param [in,out] meshes - a vector of meshes to update.
7970 * \throw If any of \a meshes is NULL.
7971 * \throw If the coordinates array is not set in any of \a meshes.
7972 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7973 * \throw If \a meshes are of different space dimension.
7975 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
7977 std::size_t sz=meshes.size();
7980 std::vector< const DataArrayDouble * > coords(meshes.size());
7981 std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7982 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7986 (*it)->checkConnectivityFullyDefined();
7987 const DataArrayDouble *coo=(*it)->getCoords();
7992 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7993 oss << " has no coordinate array defined !";
7994 throw INTERP_KERNEL::Exception(oss.str().c_str());
7999 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8000 oss << " is null !";
8001 throw INTERP_KERNEL::Exception(oss.str().c_str());
8004 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
8005 std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
8006 int offset=(*it)->getNumberOfNodes();
8007 (*it++)->setCoords(res);
8008 for(;it!=meshes.end();it++)
8010 int oldNumberOfNodes=(*it)->getNumberOfNodes();
8011 (*it)->setCoords(res);
8012 (*it)->shiftNodeNumbersInConn(offset);
8013 offset+=oldNumberOfNodes;
8018 * Merges nodes coincident with a given precision within all given meshes that share
8019 * the nodal connectivity array. The given meshes **can be of different** mesh
8020 * dimension. This method is particulary useful in MEDLoader context to build a \ref
8021 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8022 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8023 * \param [in,out] meshes - a vector of meshes to update.
8024 * \param [in] eps - the precision used to detect coincident nodes (infinite norm).
8025 * \throw If any of \a meshes is NULL.
8026 * \throw If the \a meshes do not share the same node coordinates array.
8027 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8029 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
8033 std::set<const DataArrayDouble *> s;
8034 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8037 s.insert((*it)->getCoords());
8040 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 !";
8041 throw INTERP_KERNEL::Exception(oss.str().c_str());
8046 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 !";
8047 throw INTERP_KERNEL::Exception(oss.str().c_str());
8049 const DataArrayDouble *coo=*(s.begin());
8053 DataArrayInt *comm,*commI;
8054 coo->findCommonTuples(eps,-1,comm,commI);
8055 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
8056 int oldNbOfNodes=coo->getNumberOfTuples();
8058 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
8059 if(oldNbOfNodes==newNbOfNodes)
8061 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
8062 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8064 (*it)->renumberNodesInConn(o2n->getConstPointer());
8065 (*it)->setCoords(newCoords);
8070 * 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.
8071 * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
8072 * \param isQuad specifies the policy of connectivity.
8073 * @ret in/out parameter in which the result will be append
8075 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
8077 INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
8078 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
8079 ret.push_back(cm.getExtrudedType());
8080 int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
8083 case INTERP_KERNEL::NORM_POINT1:
8085 ret.push_back(connBg[1]);
8086 ret.push_back(connBg[1]+nbOfNodesPerLev);
8089 case INTERP_KERNEL::NORM_SEG2:
8091 int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
8092 ret.insert(ret.end(),conn,conn+4);
8095 case INTERP_KERNEL::NORM_SEG3:
8097 int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8098 ret.insert(ret.end(),conn,conn+8);
8101 case INTERP_KERNEL::NORM_QUAD4:
8103 int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8104 ret.insert(ret.end(),conn,conn+8);
8107 case INTERP_KERNEL::NORM_TRI3:
8109 int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8110 ret.insert(ret.end(),conn,conn+6);
8113 case INTERP_KERNEL::NORM_TRI6:
8115 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,
8116 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8117 ret.insert(ret.end(),conn,conn+15);
8120 case INTERP_KERNEL::NORM_QUAD8:
8123 connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8124 connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8125 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8127 ret.insert(ret.end(),conn,conn+20);
8130 case INTERP_KERNEL::NORM_POLYGON:
8132 std::back_insert_iterator< std::vector<int> > ii(ret);
8133 std::copy(connBg+1,connEnd,ii);
8135 std::reverse_iterator<const int *> rConnBg(connEnd);
8136 std::reverse_iterator<const int *> rConnEnd(connBg+1);
8137 std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8138 std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8139 for(std::size_t i=0;i<nbOfRadFaces;i++)
8142 int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8143 std::copy(conn,conn+4,ii);
8148 throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8153 * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8155 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8158 double v[3]={0.,0.,0.};
8159 std::size_t sz=std::distance(begin,end);
8164 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];
8165 v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8166 v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8168 double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8170 // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8171 // SEG3 forming a circle):
8172 if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8174 v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8175 for(std::size_t j=0;j<sz;j++)
8177 if (j%2) // current point i is quadratic, next point i+1 is standard
8180 ip1 = (j+1)%sz; // ip1 = "i+1"
8182 else // current point i is standard, next point i+1 is quadratic
8187 v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8188 v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8189 v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8191 ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8197 * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8199 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8201 std::vector<std::pair<int,int> > edges;
8202 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8203 const int *bgFace=begin;
8204 for(std::size_t i=0;i<nbOfFaces;i++)
8206 const int *endFace=std::find(bgFace+1,end,-1);
8207 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8208 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8210 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8211 if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8213 edges.push_back(p1);
8217 return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8221 * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8223 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8225 double vec0[3],vec1[3];
8226 std::size_t sz=std::distance(begin,end);
8228 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8229 int nbOfNodes=(int)sz/2;
8230 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8231 const double *pt0=coords+3*begin[0];
8232 const double *pt1=coords+3*begin[nbOfNodes];
8233 vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8234 return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8237 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8239 std::size_t sz=std::distance(begin,end);
8240 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8241 std::size_t nbOfNodes(sz/2);
8242 std::copy(begin,end,(int *)tmp);
8243 for(std::size_t j=1;j<nbOfNodes;j++)
8245 begin[j]=tmp[nbOfNodes-j];
8246 begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8250 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8252 std::size_t sz=std::distance(begin,end);
8254 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8255 double vec0[3],vec1[3];
8256 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8257 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];
8258 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;
8261 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8263 std::size_t sz=std::distance(begin,end);
8265 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8267 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8268 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8269 return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8273 * 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 )
8274 * 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
8277 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8278 * \param [in] coords the coordinates with nb of components exactly equal to 3
8279 * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8280 * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8281 * \param [out] res the result is put at the end of the vector without any alteration of the data.
8283 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8285 int nbFaces=std::count(begin+1,end,-1)+1;
8286 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8287 double *vPtr=v->getPointer();
8288 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8289 double *pPtr=p->getPointer();
8290 const int *stFaceConn=begin+1;
8291 for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8293 const int *endFaceConn=std::find(stFaceConn,end,-1);
8294 ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8295 stFaceConn=endFaceConn+1;
8297 pPtr=p->getPointer(); vPtr=v->getPointer();
8298 DataArrayInt *comm1=0,*commI1=0;
8299 v->findCommonTuples(eps,-1,comm1,commI1);
8300 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8301 const int *comm1Ptr=comm1->getConstPointer();
8302 const int *commI1Ptr=commI1->getConstPointer();
8303 int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8304 res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8306 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8307 mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8308 mm->finishInsertingCells();
8310 for(int i=0;i<nbOfGrps1;i++)
8312 int vecId=comm1Ptr[commI1Ptr[i]];
8313 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8314 DataArrayInt *comm2=0,*commI2=0;
8315 tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8316 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8317 const int *comm2Ptr=comm2->getConstPointer();
8318 const int *commI2Ptr=commI2->getConstPointer();
8319 int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8320 for(int j=0;j<nbOfGrps2;j++)
8322 if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8324 res->insertAtTheEnd(begin,end);
8325 res->pushBackSilent(-1);
8329 int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8330 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8331 ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8332 DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8333 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8334 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8335 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8336 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8337 const int *idsNodePtr=idsNode->getConstPointer();
8338 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];
8339 double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8340 double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8341 if(std::abs(norm)>eps)
8343 double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8344 mm3->rotate(center,vec,angle);
8346 mm3->changeSpaceDimension(2);
8347 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8348 const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8349 const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8350 int nbOfCells=mm4->getNumberOfCells();
8351 for(int k=0;k<nbOfCells;k++)
8354 for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8355 res->pushBackSilent(idsNodePtr[*work]);
8356 res->pushBackSilent(-1);
8361 res->popBackSilent();
8365 * 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
8366 * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8368 * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8369 * \param [in] coords coordinates expected to have 3 components.
8370 * \param [in] begin start of the nodal connectivity of the face.
8371 * \param [in] end end of the nodal connectivity (excluded) of the face.
8372 * \param [out] v the normalized vector of size 3
8373 * \param [out] p the pos of plane
8375 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8377 std::size_t nbPoints=std::distance(begin,end);
8379 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8380 double vec[3]={0.,0.,0.};
8382 bool refFound=false;
8383 for(;j<nbPoints-1 && !refFound;j++)
8385 vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8386 vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8387 vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8388 double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8392 vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8395 for(std::size_t i=j;i<nbPoints-1;i++)
8398 curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8399 curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8400 curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8401 double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8404 curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8405 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];
8406 norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8409 v[0]/=norm; v[1]/=norm; v[2]/=norm;
8410 *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8414 throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8418 * This method tries to obtain a well oriented polyhedron.
8419 * If the algorithm fails, an exception will be thrown.
8421 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8423 std::list< std::pair<int,int> > edgesOK,edgesFinished;
8424 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8425 std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8427 int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8428 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8429 for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8431 while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8434 std::size_t smthChanged=0;
8435 for(std::size_t i=0;i<nbOfFaces;i++)
8437 endFace=std::find(bgFace+1,end,-1);
8438 nbOfEdgesInFace=std::distance(bgFace,endFace);
8442 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8444 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8445 std::pair<int,int> p2(p1.second,p1.first);
8446 bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8447 bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8448 if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8453 std::reverse(bgFace+1,endFace);
8454 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8456 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8457 std::pair<int,int> p2(p1.second,p1.first);
8458 if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8459 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8460 if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8461 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8462 std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8463 if(it!=edgesOK.end())
8466 edgesFinished.push_back(p1);
8469 edgesOK.push_back(p1);
8476 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8478 if(!edgesOK.empty())
8479 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8480 if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8481 {//not lucky ! The first face was not correctly oriented : reorient all faces...
8483 for(std::size_t i=0;i<nbOfFaces;i++)
8485 endFace=std::find(bgFace+1,end,-1);
8486 std::reverse(bgFace+1,endFace);
8492 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8494 int nbOfNodesExpected(skin->getNumberOfNodes());
8495 const int *n2oPtr(n2o->getConstPointer());
8496 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8497 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8498 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8499 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8500 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8501 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8502 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_POLYGON;
8503 if(nbOfNodesExpected<1)
8505 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8506 *work++=n2oPtr[prevNode];
8507 for(int i=1;i<nbOfNodesExpected;i++)
8509 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8511 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8512 conn.erase(prevNode);
8515 int curNode(*(conn.begin()));
8516 *work++=n2oPtr[curNode];
8517 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8518 shar.erase(prevCell);
8521 prevCell=*(shar.begin());
8525 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8528 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8531 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8536 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8538 int nbOfNodesExpected(skin->getNumberOfNodes());
8539 int nbOfTurn(nbOfNodesExpected/2);
8540 const int *n2oPtr(n2o->getConstPointer());
8541 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8542 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8543 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8544 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8545 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8546 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8547 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_QPOLYG;
8548 if(nbOfNodesExpected<1)
8550 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8551 *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8552 for(int i=1;i<nbOfTurn;i++)
8554 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8556 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8557 conn.erase(prevNode);
8560 int curNode(*(conn.begin()));
8561 *work=n2oPtr[curNode];
8562 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8563 shar.erase(prevCell);
8566 int curCell(*(shar.begin()));
8567 work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8573 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8576 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8579 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8585 * This method makes the assumption spacedimension == meshdimension == 2.
8586 * This method works only for linear cells.
8588 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8590 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8592 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8593 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8594 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8595 int oldNbOfNodes(skin->getNumberOfNodes());
8596 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8597 int nbOfNodesExpected(skin->getNumberOfNodes());
8598 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8599 int nbCells(skin->getNumberOfCells());
8600 if(nbCells==nbOfNodesExpected)
8601 return buildUnionOf2DMeshLinear(skin,n2o);
8602 else if(2*nbCells==nbOfNodesExpected)
8603 return buildUnionOf2DMeshQuadratic(skin,n2o);
8605 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8609 * This method makes the assumption spacedimension == meshdimension == 3.
8610 * This method works only for linear cells.
8612 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8614 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8616 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8617 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8618 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8619 const int *conn=m->getNodalConnectivity()->getConstPointer();
8620 const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8621 int nbOfCells=m->getNumberOfCells();
8622 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8623 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED;
8626 work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8627 for(int i=1;i<nbOfCells;i++)
8630 work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8636 * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8637 * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8639 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8643 for(int i=0;i<nbOfNodesInCell;i++)
8644 w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8645 else if(spaceDim==2)
8647 for(int i=0;i<nbOfNodesInCell;i++)
8649 w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8654 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8657 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8659 int nbOfCells=getNumberOfCells();
8661 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8662 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};
8663 ofs << " <" << getVTKDataSetType() << ">\n";
8664 ofs << " <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8665 ofs << " <PointData>\n" << pointData << std::endl;
8666 ofs << " </PointData>\n";
8667 ofs << " <CellData>\n" << cellData << std::endl;
8668 ofs << " </CellData>\n";
8669 ofs << " <Points>\n";
8670 if(getSpaceDimension()==3)
8671 _coords->writeVTK(ofs,8,"Points",byteData);
8674 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8675 coo->writeVTK(ofs,8,"Points",byteData);
8677 ofs << " </Points>\n";
8678 ofs << " <Cells>\n";
8679 const int *cPtr=_nodal_connec->getConstPointer();
8680 const int *cIPtr=_nodal_connec_index->getConstPointer();
8681 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8682 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8683 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8684 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8685 int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8686 int szFaceOffsets=0,szConn=0;
8687 for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8690 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8693 *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8694 w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8698 int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8699 *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8700 std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8701 *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8702 w4=std::copy(c.begin(),c.end(),w4);
8705 types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8706 types->writeVTK(ofs,8,"UInt8","types",byteData);
8707 offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8708 if(szFaceOffsets!=0)
8709 {//presence of Polyhedra
8710 connectivity->reAlloc(szConn);
8711 faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8712 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8713 w1=faces->getPointer();
8714 for(int i=0;i<nbOfCells;i++)
8715 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8717 int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8719 const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8720 for(int j=0;j<nbFaces;j++)
8722 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8723 *w1++=(int)std::distance(w6,w5);
8724 w1=std::copy(w6,w5,w1);
8728 faces->writeVTK(ofs,8,"Int32","faces",byteData);
8730 connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8731 ofs << " </Cells>\n";
8732 ofs << " </Piece>\n";
8733 ofs << " </" << getVTKDataSetType() << ">\n";
8736 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8738 stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8740 { stream << " Not set !"; return ; }
8741 stream << " Mesh dimension : " << _mesh_dim << ".";
8745 { stream << " No coordinates set !"; return ; }
8746 if(!_coords->isAllocated())
8747 { stream << " Coordinates set but not allocated !"; return ; }
8748 stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8749 stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8750 if(!_nodal_connec_index)
8751 { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8752 if(!_nodal_connec_index->isAllocated())
8753 { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8754 int lgth=_nodal_connec_index->getNumberOfTuples();
8755 int cpt=_nodal_connec_index->getNumberOfComponents();
8756 if(cpt!=1 || lgth<1)
8758 stream << std::endl << "Number of cells : " << lgth-1 << ".";
8761 std::string MEDCouplingUMesh::getVTKDataSetType() const
8763 return std::string("UnstructuredGrid");
8766 std::string MEDCouplingUMesh::getVTKFileExtension() const
8768 return std::string("vtu");
8772 * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8773 * returns a result mesh constituted by polygons.
8774 * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8775 * all nodes from m2.
8776 * The meshes should be in 2D space. In
8777 * addition, returns two arrays mapping cells of the result mesh to cells of the input
8779 * \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
8780 * 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)
8781 * \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
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] eps - precision used to detect coincident mesh entities.
8784 * \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8785 * cell an id of the cell of \a m1 it comes from. The caller is to delete
8786 * this array using decrRef() as it is no more needed.
8787 * \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8788 * cell an id of the cell of \a m2 it comes from. -1 value means that a
8789 * result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8790 * any cell of \a m2. The caller is to delete this array using decrRef() as
8791 * it is no more needed.
8792 * \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8793 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8794 * is no more needed.
8795 * \throw If the coordinates array is not set in any of the meshes.
8796 * \throw If the nodal connectivity of cells is not defined in any of the meshes.
8797 * \throw If any of the meshes is not a 2D mesh in 2D space.
8799 * \sa conformize2D, mergeNodes
8801 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8802 double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8805 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
8806 m1->checkFullyDefined();
8807 m2->checkFullyDefined();
8808 if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8809 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!");
8811 // Step 1: compute all edge intersections (new nodes)
8812 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8813 MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
8814 DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8815 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
8816 IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
8817 m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8818 addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
8819 revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8820 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8821 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8823 // Step 2: re-order newly created nodes according to the ordering found in m2
8824 std::vector< std::vector<int> > intersectEdge2;
8825 BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8826 subDiv2.clear(); dd5=0; dd6=0;
8829 std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8830 std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8831 BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8832 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8834 // Step 4: Prepare final result:
8835 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
8836 addCooDa->alloc((int)(addCoo.size())/2,2);
8837 std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8838 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
8839 addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8840 std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8841 std::vector<const DataArrayDouble *> coordss(4);
8842 coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8843 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
8844 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
8845 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8846 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8847 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8848 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8849 ret->setConnectivity(conn,connI,true);
8850 ret->setCoords(coo);
8851 cellNb1=c1.retn(); cellNb2=c2.retn();
8857 bool IsColinearOfACellOf(const std::vector< std::vector<int> >& intersectEdge1, const std::vector<int>& candidates, int start, int stop, int& retVal)
8859 if(candidates.empty())
8861 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
8863 const std::vector<int>& pool(intersectEdge1[*it]);
8864 int tmp[2]; tmp[0]=start; tmp[1]=stop;
8865 if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
8870 tmp[0]=stop; tmp[1]=start;
8871 if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
8880 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,
8881 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInRetColinear, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInMesh1DForIdsInRetColinear)
8883 idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1);
8884 idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1);
8885 int nCells(mesh1D->getNumberOfCells());
8886 if(nCells!=(int)intersectEdge2.size())
8887 throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
8888 const DataArrayDouble *coo2(mesh1D->getCoords());
8889 const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
8890 const double *coo2Ptr(coo2->begin());
8891 int offset1(coords1->getNumberOfTuples());
8892 int offset2(offset1+coo2->getNumberOfTuples());
8893 int offset3(offset2+addCoo.size()/2);
8894 std::vector<double> addCooQuad;
8895 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
8896 int tmp[4],cicnt(0),kk(0);
8897 for(int i=0;i<nCells;i++)
8899 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
8900 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
8901 const std::vector<int>& subEdges(intersectEdge2[i]);
8902 int nbSubEdge(subEdges.size()/2);
8903 for(int j=0;j<nbSubEdge;j++,kk++)
8905 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));
8906 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
8907 INTERP_KERNEL::Edge *e2Ptr(e2);
8908 std::map<int,int>::const_iterator itm;
8909 if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
8911 tmp[0]=INTERP_KERNEL::NORM_SEG3;
8912 itm=mergedNodes.find(subEdges[2*j]);
8913 tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
8914 itm=mergedNodes.find(subEdges[2*j+1]);
8915 tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
8916 tmp[3]=offset3+(int)addCooQuad.size()/2;
8918 e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2);
8920 cOut->insertAtTheEnd(tmp,tmp+4);
8921 ciOut->pushBackSilent(cicnt);
8925 tmp[0]=INTERP_KERNEL::NORM_SEG2;
8926 itm=mergedNodes.find(subEdges[2*j]);
8927 tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
8928 itm=mergedNodes.find(subEdges[2*j+1]);
8929 tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
8931 cOut->insertAtTheEnd(tmp,tmp+3);
8932 ciOut->pushBackSilent(cicnt);
8935 if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00))
8937 idsInRetColinear->pushBackSilent(kk);
8938 idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00);
8943 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
8944 ret->setConnectivity(cOut,ciOut,true);
8945 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr3(DataArrayDouble::New());
8946 arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
8947 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
8948 std::vector<const DataArrayDouble *> coordss(4);
8949 coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
8950 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
8951 ret->setCoords(arr);
8955 MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
8957 std::vector<int> allEdges;
8958 for(const int *it2(descBg);it2!=descEnd;it2++)
8960 const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
8962 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
8964 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
8966 std::size_t nb(allEdges.size());
8968 throw INTERP_KERNEL::Exception("BuildRefined2DCell : internal error 1 !");
8969 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
8970 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
8971 ret->setCoords(coords);
8972 ret->allocateCells(1);
8973 std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
8974 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
8975 connOut[kk]=allEdges[2*kk];
8976 ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]);
8980 void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector<int>& conn, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edges)
8983 for(std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >::const_iterator it=edges.begin();it!=edges.end();it++)
8985 const INTERP_KERNEL::Edge *ee(*it);
8986 if(dynamic_cast<const INTERP_KERNEL::EdgeArcCircle *>(ee))
8990 mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]);
8993 const double *coo(mesh2D->getCoords()->begin());
8994 std::size_t sz(conn.size());
8995 std::vector<double> addCoo;
8996 std::vector<int> conn2(conn);
8997 int offset(mesh2D->getNumberOfNodes());
8998 for(std::size_t i=0;i<sz;i++)
9001 edges[(i+1)%sz]->getMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);
9002 addCoo.insert(addCoo.end(),tmp,tmp+2);
9003 conn2.push_back(offset+(int)i);
9005 mesh2D->getCoords()->rearrange(1);
9006 mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size());
9007 mesh2D->getCoords()->rearrange(2);
9008 mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]);
9013 * \b WARNING edges in out1 coming from \a splitMesh1D are \b NOT oriented because only used for equation of curve.
9015 void BuildMesh2DCutInternal2(const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& edge1Bis, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edge1BisPtr,
9016 std::vector< std::vector<int> >& out0, std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& out1)
9018 std::size_t nb(edge1Bis.size()/2);
9019 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9020 int iEnd(splitMesh1D->getNumberOfCells());
9022 throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal2 : internal error ! input 1D mesh must have at least one cell !");
9024 const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9025 for(ii=0;ii<nb && edge1Bis[2*ii]!=cSplitPtr[ciSplitPtr[0]+1];ii++);
9026 for(jj=ii;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd-1]+2];jj++);
9029 {//the edges splitMesh1D[iStart:iEnd] does not fully cut the current 2D cell -> single output cell
9030 out0.resize(1); out1.resize(1);
9031 std::vector<int>& connOut(out0[0]);
9032 connOut.resize(nbOfEdgesOf2DCellSplit);
9033 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr(out1[0]);
9034 edgesPtr.resize(nbOfEdgesOf2DCellSplit);
9035 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9037 connOut[kk]=edge1Bis[2*kk];
9038 edgesPtr[kk]=edge1BisPtr[2*kk];
9043 // [i,iEnd[ contains the
9044 out0.resize(2); out1.resize(2);
9045 std::vector<int>& connOutLeft(out0[0]);
9046 std::vector<int>& connOutRight(out0[1]);//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1]
9047 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eleft(out1[0]);
9048 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eright(out1[1]);
9049 for(std::size_t k=ii;k<jj+1;k++)
9050 { connOutLeft.push_back(edge1Bis[2*k+1]); eleft.push_back(edge1BisPtr[2*k+1]); }
9051 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > ees(iEnd);
9052 for(int ik=iEnd-1;ik>=0;ik--)
9054 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9055 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9058 for(int ik=iEnd-1;ik>=0;ik--)
9059 connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]);
9060 for(std::size_t k=jj+1;k<nbOfEdgesOf2DCellSplit+ii;k++)
9061 { connOutRight.push_back(edge1Bis[2*k+1]); eright.push_back(edge1BisPtr[2*k+1]); }
9062 eleft.insert(eleft.end(),ees.begin(),ees.end());
9063 for(int ik=0;ik<iEnd;ik++)
9064 connOutRight.push_back(cSplitPtr[ciSplitPtr[ik]+2]);
9065 eright.insert(eright.end(),ees.rbegin(),ees.rend());
9077 CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9079 std::vector<int> _edges;
9080 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > _edges_ptr;
9083 CellInfo::CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr)
9085 std::size_t nbe(edges.size());
9086 std::vector<int> edges2(2*nbe); std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edgesPtr2(2*nbe);
9087 for(std::size_t i=0;i<nbe;i++)
9089 edges2[2*i]=edges[i]; edges2[2*i+1]=edges[(i+1)%nbe];
9090 edgesPtr2[2*i]=edgesPtr[i]; edgesPtr2[2*i+1]=edgesPtr[i];
9092 _edges.resize(4*nbe); _edges_ptr.resize(4*nbe);
9093 std::copy(edges2.begin(),edges2.end(),_edges.begin()); std::copy(edges2.begin(),edges2.end(),_edges.begin()+2*nbe);
9094 std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()); std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()+2*nbe);
9100 EdgeInfo(int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh):_istart(istart),_iend(iend),_mesh(mesh),_left(-7),_right(-7) { }
9101 EdgeInfo(int istart, int iend, int pos, const MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge>& edge):_istart(istart),_iend(iend),_edge(edge),_left(pos),_right(pos+1) { }
9102 bool isInMyRange(int pos) const { return pos>=_istart && pos<_iend; }
9103 void somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9104 void feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const;
9108 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _mesh;
9109 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> _edge;
9114 void EdgeInfo::somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9116 const MEDCouplingUMesh *mesh(_mesh);
9122 { _left++; _right++; return ; }
9125 bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9126 if((isLeft && isRight) || (!isLeft && !isRight))
9127 throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 1 !");
9138 bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9139 if((isLeft && isRight) || (!isLeft && !isRight))
9140 throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 2 !");
9155 void EdgeInfo::feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const
9157 const MEDCouplingUMesh *mesh(_mesh);
9160 neighbors[0]=offset+_left; neighbors[1]=offset+_right;
9163 {// not fully splitting cell case
9164 if(mesh2D->getNumberOfCells()==1)
9165 {//little optimization. 1 cell no need to find in which cell mesh is !
9166 neighbors[0]=offset; neighbors[1]=offset;
9171 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9172 int cellId(mesh2D->getCellContainingPoint(barys->begin(),eps));
9174 throw INTERP_KERNEL::Exception("EdgeInfo::feedEdgeInfoAt : internal error !");
9175 neighbors[0]=offset+cellId; neighbors[1]=offset+cellId;
9180 class VectorOfCellInfo
9183 VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9184 std::size_t size() const { return _pool.size(); }
9185 int getPositionOf(double eps, const MEDCouplingUMesh *mesh) const;
9186 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);
9187 const std::vector<int>& getConnOf(int pos) const { return get(pos)._edges; }
9188 const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& getEdgePtrOf(int pos) const { return get(pos)._edges_ptr; }
9189 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> getZeMesh() const { return _ze_mesh; }
9190 void feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const;
9192 int getZePosOfEdgeGivenItsGlobalId(int pos) const;
9193 void updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9194 const CellInfo& get(int pos) const;
9195 CellInfo& get(int pos);
9197 std::vector<CellInfo> _pool;
9198 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _ze_mesh;
9199 std::vector<EdgeInfo> _edge_info;
9202 VectorOfCellInfo::VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr):_pool(1)
9204 _pool[0]._edges=edges;
9205 _pool[0]._edges_ptr=edgesPtr;
9208 int VectorOfCellInfo::getPositionOf(double eps, const MEDCouplingUMesh *mesh) const
9211 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : empty !");
9214 const MEDCouplingUMesh *zeMesh(_ze_mesh);
9216 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : null aggregated mesh !");
9217 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9218 return zeMesh->getCellContainingPoint(barys->begin(),eps);
9221 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)
9223 get(pos);//to check pos
9224 bool isFast(pos==0 && _pool.size()==1);
9225 std::size_t sz(edges.size());
9226 // dealing with edges
9228 _edge_info.push_back(EdgeInfo(istart,iend,mesh1DInCase));
9230 _edge_info.push_back(EdgeInfo(istart,iend,pos,edgePtrs[0].back()));
9232 std::vector<CellInfo> pool(_pool.size()-1+sz);
9233 for(int i=0;i<pos;i++)
9235 for(std::size_t j=0;j<sz;j++)
9236 pool[pos+j]=CellInfo(edges[j],edgePtrs[j]);
9237 for(int i=pos+1;i<(int)_pool.size();i++)
9238 pool[pos+sz-1]=_pool[i];
9242 updateEdgeInfo(pos,edgePtrs[0],edgePtrs[1]);
9250 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > ms;
9253 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(0,pos,true)));
9257 if(pos<_ze_mesh->getNumberOfCells()-1)
9259 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(pos+1,_ze_mesh->getNumberOfCells(),true)));
9262 std::vector< const MEDCouplingUMesh *> ms2(ms.size());
9263 for(std::size_t j=0;j<ms2.size();j++)
9265 _ze_mesh=MEDCouplingUMesh::MergeUMeshesOnSameCoords(ms2);
9268 void VectorOfCellInfo::feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const
9270 _edge_info[getZePosOfEdgeGivenItsGlobalId(pos)].feedEdgeInfoAt(eps,_ze_mesh,offset,neighbors);
9273 int VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId(int pos) const
9276 throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id ! Must be >=0 !");
9278 for(std::vector<EdgeInfo>::const_iterator it=_edge_info.begin();it!=_edge_info.end();it++,ret++)
9280 if((*it).isInMyRange(pos))
9283 throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id !");
9286 void VectorOfCellInfo::updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9288 get(pos);//to check;
9289 if(_edge_info.empty())
9291 std::size_t sz(_edge_info.size()-1);
9292 for(std::size_t i=0;i<sz;i++)
9293 _edge_info[i].somethingHappendAt(pos,newLeft,newRight);
9296 const CellInfo& VectorOfCellInfo::get(int pos) const
9298 if(pos<0 || pos>=(int)_pool.size())
9299 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get const : invalid pos !");
9303 CellInfo& VectorOfCellInfo::get(int pos)
9305 if(pos<0 || pos>=(int)_pool.size())
9306 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get : invalid pos !");
9310 MEDCouplingUMesh *BuildMesh2DCutInternal(double eps, const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& allEdges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& allEdgesPtr, int offset,
9311 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9313 int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells());
9314 if(nbCellsInSplitMesh1D==0)
9315 throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal : internal error ! input 1D mesh must have at least one cell !");
9316 const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9317 std::size_t nb(allEdges.size()),jj;
9319 throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !");
9320 std::vector<int> edge1Bis(nb*2);
9321 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edge1BisPtr(nb*2);
9322 std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin());
9323 std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb);
9324 std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin());
9325 std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb);
9327 idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(nbCellsInSplitMesh1D*2); idsLeftRight->fillWithValue(-2); idsLeftRight->rearrange(2);
9328 int *idsLeftRightPtr(idsLeftRight->getPointer());
9329 VectorOfCellInfo pool(edge1Bis,edge1BisPtr);
9330 for(int iStart=0;iStart<nbCellsInSplitMesh1D;)
9331 {// split [0:nbCellsInSplitMesh1D) in contiguous parts [iStart:iEnd)
9333 for(;iEnd<nbCellsInSplitMesh1D;)
9335 for(jj=0;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd]+2];jj++);
9341 if(iEnd<nbCellsInSplitMesh1D)
9344 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfSplitMesh1D(static_cast<MEDCouplingUMesh *>(splitMesh1D->buildPartOfMySelf2(iStart,iEnd,1,true)));
9345 int pos(pool.getPositionOf(eps,partOfSplitMesh1D));
9347 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>retTmp(MEDCouplingUMesh::New("",2));
9348 retTmp->setCoords(splitMesh1D->getCoords());
9349 retTmp->allocateCells();
9351 std::vector< std::vector<int> > out0;
9352 std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > > out1;
9354 BuildMesh2DCutInternal2(partOfSplitMesh1D,pool.getConnOf(pos),pool.getEdgePtrOf(pos),out0,out1);
9355 for(std::size_t cnt=0;cnt<out0.size();cnt++)
9356 AddCellInMesh2D(retTmp,out0[cnt],out1[cnt]);
9357 pool.setMeshAt(pos,retTmp,iStart,iEnd,partOfSplitMesh1D,out0,out1);
9361 for(int mm=0;mm<nbCellsInSplitMesh1D;mm++)
9362 pool.feedEdgeInfoAt(eps,mm,offset,idsLeftRightPtr+2*mm);
9363 return pool.getZeMesh().retn();
9366 MEDCouplingUMesh *BuildMesh2DCutFrom(double eps, int cellIdInMesh2D, const MEDCouplingUMesh *mesh2DDesc, const MEDCouplingUMesh *splitMesh1D,
9367 const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1, int offset,
9368 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9370 const int *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin());
9372 std::vector<int> allEdges;
9373 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > allEdgesPtr;
9374 for(const int *it(descBg);it!=descEnd;it++)
9376 int edgeId(std::abs(*it)-1);
9377 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9378 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m));
9379 const std::vector<int>& edge1(intersectEdge1[edgeId]);
9381 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9383 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9384 std::size_t sz(edge1.size());
9385 for(std::size_t cnt=0;cnt<sz;cnt++)
9386 allEdgesPtr.push_back(ee);
9389 return BuildMesh2DCutInternal(eps,splitMesh1D,allEdges,allEdgesPtr,offset,idsLeftRight);
9395 * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
9396 * 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
9397 * and finaly, in case of quadratic polygon the centers of edges new nodes.
9398 * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
9400 * \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
9401 * 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)
9402 * \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
9403 * you can invoke orderConsecutiveCells1D on \a mesh1D.
9404 * \param [in] eps - precision used to perform intersections and localization operations.
9405 * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
9406 * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
9407 * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
9408 * 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.
9409 * \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
9410 * and the cell in \a splitMesh2D on the right for the 2nt component. -1 means no cell.
9411 * 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.
9413 * \sa Intersect2DMeshes, orderConsecutiveCells1D, conformize2D, mergeNodes
9415 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
9417 if(!mesh2D || !mesh1D)
9418 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
9419 mesh2D->checkFullyDefined();
9420 mesh1D->checkFullyDefined();
9421 const std::vector<std::string>& compNames(mesh2D->getCoords()->getInfoOnComponents());
9422 if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
9423 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
9424 // Step 1: compute all edge intersections (new nodes)
9425 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9426 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
9427 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9428 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9430 // Build desc connectivity
9431 DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
9432 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9433 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
9434 std::map<int,int> mergedNodes;
9435 Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes);
9436 // use mergeNodes to fix intersectEdge1
9437 for(std::vector< std::vector<int> >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++)
9439 std::size_t n((*it0).size()/2);
9440 int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]);
9441 std::map<int,int>::const_iterator it1;
9442 it1=mergedNodes.find(eltStart);
9443 if(it1!=mergedNodes.end())
9444 (*it0)[0]=(*it1).second;
9445 it1=mergedNodes.find(eltEnd);
9446 if(it1!=mergedNodes.end())
9447 (*it0)[2*n-1]=(*it1).second;
9450 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9451 addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9452 // Step 2: re-order newly created nodes according to the ordering found in m2
9453 std::vector< std::vector<int> > intersectEdge2;
9454 BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
9456 // Step 3: compute splitMesh1D
9457 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear;
9458 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2(DataArrayInt::New()); ret2->alloc(0,1);
9459 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1,
9460 idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear));
9461 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(-1); ret3->rearrange(2);
9462 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells()));
9463 // deal with cells in mesh2D that are not cut but only some of their edges are
9464 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCpy());
9465 idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1);
9466 idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique();
9467 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
9468 if(!idsInDesc2DToBeRefined->empty())
9470 DataArrayInt *out0(0),*outi0(0);
9471 MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
9472 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> outi0s(outi0);
9474 out0s=out0s->buildUnique();
9478 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1NonCol(static_cast<MEDCouplingUMesh *>(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end())));
9479 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> baryRet1(ret1NonCol->getBarycenterAndOwner());
9480 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elts,eltsIndex;
9481 mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
9482 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex2(eltsIndex->deltaShiftIndex());
9483 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex3(eltsIndex2->getIdsEqual(1));
9484 if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells())
9485 throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !");
9486 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToBeModified(elts->buildUnique());
9487 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells()));
9488 if((DataArrayInt *)out0s)
9489 untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one
9490 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > outMesh2DSplit;
9491 // OK all is ready to insert in ret2 mesh
9492 if(!untouchedCells->empty())
9493 {// the most easy part, cells in mesh2D not impacted at all
9494 outMesh2DSplit.push_back(static_cast<MEDCouplingUMesh *>(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end())));
9495 outMesh2DSplit.back()->setCoords(ret1->getCoords());
9496 ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end());
9498 if((DataArrayInt *)out0s)
9499 {// here dealing with cells in out0s but not in cellsToBeModified
9500 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fewModifiedCells(out0s->buildSubstraction(cellsToBeModified));
9501 const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin());
9502 for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++)
9504 outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1));
9506 int offset(ret2->getNumberOfTuples());
9507 ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end());
9508 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1);
9509 partOfRet3->fillWithValue(-1); partOfRet3->rearrange(2);
9510 int kk(0),*ret3ptr(partOfRet3->getPointer());
9511 for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++)
9513 int faceId(std::abs(*it)-1);
9514 for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++)
9516 int tmp(fewModifiedCells->locateValue(*it2));
9519 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9520 ret3ptr[2*kk]=tmp+offset;
9521 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9522 ret3ptr[2*kk+1]=tmp+offset;
9525 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : internal error 1 !");
9528 ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true);
9530 for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++)
9532 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell(elts->getIdsEqual(*it));
9533 idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end());
9534 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end()));
9535 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfMesh1CuttingCur2DCell(static_cast<MEDCouplingUMesh *>(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end())));
9536 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3;
9537 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));
9538 ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true);
9539 outMesh2DSplit.push_back(splitOfOneCell);
9540 for(int i=0;i<splitOfOneCell->getNumberOfCells();i++)
9541 ret2->pushBackSilent(*it);
9544 std::size_t nbOfMeshes(outMesh2DSplit.size());
9545 std::vector<const MEDCouplingUMesh *> tmp(nbOfMeshes);
9546 for(std::size_t i=0;i<nbOfMeshes;i++)
9547 tmp[i]=outMesh2DSplit[i];
9549 ret1->getCoords()->setInfoOnComponents(compNames);
9551 splitMesh1D=ret1.retn();
9552 splitMesh2D=MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp);
9553 cellIdInMesh2D=ret2.retn();
9554 cellIdInMesh1D=ret3.retn();
9558 * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
9559 * (newly created) nodes corresponding to the edge intersections.
9561 * @param[out] cr, crI connectivity of the resulting mesh
9562 * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
9563 * TODO: describe input parameters
9565 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
9566 const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
9567 const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
9568 const std::vector<double>& addCoords,
9569 std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
9571 static const int SPACEDIM=2;
9572 const double *coo1(m1->getCoords()->getConstPointer());
9573 const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer());
9574 int offset1(m1->getNumberOfNodes());
9575 const double *coo2(m2->getCoords()->getConstPointer());
9576 const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer());
9577 int offset2(offset1+m2->getNumberOfNodes());
9578 int offset3(offset2+((int)addCoords.size())/2);
9579 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
9580 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9581 // Here a BBTree on 2D-cells, not on segments:
9582 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
9583 int ncell1(m1->getNumberOfCells());
9585 for(int i=0;i<ncell1;i++)
9587 std::vector<int> candidates2;
9588 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9589 std::map<INTERP_KERNEL::Node *,int> mapp;
9590 std::map<int,INTERP_KERNEL::Node *> mappRev;
9591 INTERP_KERNEL::QuadraticPolygon pol1;
9592 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
9593 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
9594 // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
9595 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
9596 // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
9597 pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
9598 desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
9600 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
9601 std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
9602 INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
9603 for(it1.first();!it1.finished();it1.next())
9604 edges1.insert(it1.current()->getPtr());
9606 std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
9607 std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
9609 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9611 INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
9612 const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
9613 // Complete mapping with elements coming from the current cell it2 in mesh2:
9614 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
9615 // pol2 is the new QP in the final merged result.
9616 pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
9617 pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
9620 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9622 INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
9623 pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
9624 //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
9625 pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9627 // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
9628 // by m2 but that we still want to keep in the final result.
9633 INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9635 catch(INTERP_KERNEL::Exception& e)
9637 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();
9638 throw INTERP_KERNEL::Exception(oss.str().c_str());
9641 for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
9642 (*it).second->decrRef();
9647 * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
9648 * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
9649 * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
9650 * The caller is to deal with the resulting DataArrayInt.
9651 * \throw If the coordinate array is not set.
9652 * \throw If the nodal connectivity of the cells is not defined.
9653 * \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
9654 * \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
9656 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
9658 checkFullyDefined();
9659 if(getMeshDimension()!=1)
9660 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
9662 // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
9663 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
9664 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
9665 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
9666 const int *d(_d->getConstPointer()), *dI(_dI->getConstPointer());
9667 const int *rD(_rD->getConstPointer()), *rDI(_rDI->getConstPointer());
9668 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
9669 const int * dsi(_dsi->getConstPointer());
9670 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dsii = _dsi->getIdsNotInRange(0,3);
9672 if (dsii->getNumberOfTuples())
9673 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
9675 int nc(getNumberOfCells());
9676 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> result(DataArrayInt::New());
9677 result->alloc(nc,1);
9679 // set of edges not used so far
9680 std::set<int> edgeSet;
9681 for (int i=0; i<nc; edgeSet.insert(i), i++);
9685 // while we have points with only one neighbor segments
9688 std::list<int> linePiece;
9689 // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
9690 for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
9692 // Fill the list forward (resp. backward) from the start segment:
9693 int activeSeg = startSeg;
9694 int prevPointId = -20;
9696 while (!edgeSet.empty())
9698 if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
9701 linePiece.push_back(activeSeg);
9703 linePiece.push_front(activeSeg);
9704 edgeSet.erase(activeSeg);
9707 int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
9708 ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
9709 if (dsi[ptId] == 1) // hitting the end of the line
9712 int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
9713 activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
9716 // Done, save final piece into DA:
9717 std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
9718 newIdx += linePiece.size();
9720 // identify next valid start segment (one which is not consumed)
9721 if(!edgeSet.empty())
9722 startSeg = *(edgeSet.begin());
9724 while (!edgeSet.empty());
9725 return result.retn();
9730 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
9732 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> nTmp(n); nTmp->incrRef();
9733 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>::const_iterator it(m.find(nTmp));
9735 throw INTERP_KERNEL::Exception("Internal error in remapping !");
9736 int v((*it).second);
9737 if(v==forbVal0 || v==forbVal1)
9739 if(std::find(isect.begin(),isect.end(),v)==isect.end())
9743 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
9748 bool presenceOfOn(false);
9749 for(int i=0;i<sz;i++)
9751 INTERP_KERNEL::ElementaryEdge *e(c[i]);
9752 if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
9754 IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
9755 IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
9757 return presenceOfOn;
9763 * 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.
9764 * 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.
9765 * 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.
9766 * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to avoid to have a non conform mesh.
9768 * \return int - the number of new nodes created (in most of cases 0).
9770 * \throw If \a this is not coherent.
9771 * \throw If \a this has not spaceDim equal to 2.
9772 * \throw If \a this has not meshDim equal to 2.
9773 * \throw If some subcells needed to be split are orphan.
9774 * \sa MEDCouplingUMesh::conformize2D
9776 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
9778 if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
9779 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
9780 desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
9781 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
9782 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
9783 if(midOpt==0 && midOptI==0)
9785 split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
9788 else if(midOpt!=0 && midOptI!=0)
9789 return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
9791 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
9795 * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
9796 * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
9797 * 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
9798 * 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).
9799 * 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.
9801 * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
9802 * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
9804 * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
9805 * This method expects that all nodes in \a this are not closer than \a eps.
9806 * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
9808 * \param [in] eps the relative error to detect merged edges.
9809 * \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
9810 * that the user is expected to deal with.
9812 * \throw If \a this is not coherent.
9813 * \throw If \a this has not spaceDim equal to 2.
9814 * \throw If \a this has not meshDim equal to 2.
9815 * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
9817 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
9819 static const int SPACEDIM=2;
9821 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
9822 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
9823 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
9824 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
9825 const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
9826 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
9827 const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
9828 int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
9829 std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
9830 std::vector<double> addCoo;
9831 BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
9832 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9833 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9834 for(int i=0;i<nDescCell;i++)
9836 std::vector<int> candidates;
9837 myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
9838 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
9841 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9842 INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
9843 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
9844 INTERP_KERNEL::MergePoints merge;
9845 INTERP_KERNEL::QuadraticPolygon c1,c2;
9846 e1->intersectWith(e2,merge,c1,c2);
9847 e1->decrRef(); e2->decrRef();
9848 if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
9849 overlapEdge[i].push_back(*it);
9850 if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
9851 overlapEdge[*it].push_back(i);
9854 // splitting done. sort intersect point in intersectEdge.
9855 std::vector< std::vector<int> > middle(nDescCell);
9856 int nbOf2DCellsToBeSplit(0);
9857 bool middleNeedsToBeUsed(false);
9858 std::vector<bool> cells2DToTreat(nDescCell,false);
9859 for(int i=0;i<nDescCell;i++)
9861 std::vector<int>& isect(intersectEdge[i]);
9862 int sz((int)isect.size());
9865 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9866 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
9867 e->sortSubNodesAbs(coords,isect);
9872 int idx0(rdi[i]),idx1(rdi[i+1]);
9874 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
9875 if(!cells2DToTreat[rd[idx0]])
9877 cells2DToTreat[rd[idx0]]=true;
9878 nbOf2DCellsToBeSplit++;
9880 // try to reuse at most eventual 'middle' of SEG3
9881 std::vector<int>& mid(middle[i]);
9882 mid.resize(sz+1,-1);
9883 if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
9885 middleNeedsToBeUsed=true;
9886 const std::vector<int>& candidates(overlapEdge[i]);
9887 std::vector<int> trueCandidates;
9888 for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
9889 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
9890 trueCandidates.push_back(*itc);
9891 int stNode(c[ci[i]+1]),endNode(isect[0]);
9892 for(int j=0;j<sz+1;j++)
9894 for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
9896 int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
9897 if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
9898 { mid[j]=*itc; break; }
9901 endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
9906 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
9907 if(nbOf2DCellsToBeSplit==0)
9910 int *retPtr(ret->getPointer());
9911 for(int i=0;i<nCell;i++)
9912 if(cells2DToTreat[i])
9915 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
9916 DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
9917 MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
9918 DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
9919 if(middleNeedsToBeUsed)
9920 { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
9921 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
9922 int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
9923 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.
9924 setPartOfMySelf(ret->begin(),ret->end(),*modif);
9926 bool areNodesMerged; int newNbOfNodes;
9927 if(nbOfNodesCreated!=0)
9928 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
9934 * 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.
9935 * 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).
9936 * 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
9937 * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
9938 * 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
9939 * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
9941 * 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
9942 * using new instance, idem for coordinates.
9944 * 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.
9946 * \return DataArrayInt * - The list of cellIds in \a this that have at least one edge colinearized.
9948 * \throw If \a this is not coherent.
9949 * \throw If \a this has not spaceDim equal to 2.
9950 * \throw If \a this has not meshDim equal to 2.
9952 * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
9954 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
9956 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
9958 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
9959 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
9960 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9961 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9962 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
9963 const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
9964 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
9965 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
9966 const double *coords(_coords->begin());
9967 int *newciptr(newci->getPointer());
9968 for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
9970 if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
9971 ret->pushBackSilent(i);
9972 newciptr[1]=newc->getNumberOfTuples();
9977 if(!appendedCoords->empty())
9979 appendedCoords->rearrange(2);
9980 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
9982 setCoords(newCoords);
9985 setConnectivity(newc,newci,true);
9990 * \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.
9991 * 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.
9992 * And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
9993 * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
9994 * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
9995 * \param [out] addCoo - nodes to be append at the end
9996 * \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.
9998 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
9999 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)
10001 static const int SPACEDIM=2;
10002 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10003 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10004 const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer());
10005 // Build BB tree of all edges in the tool mesh (second mesh)
10006 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
10007 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10008 int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
10009 intersectEdge1.resize(nDescCell1);
10010 colinear2.resize(nDescCell2);
10011 subDiv2.resize(nDescCell2);
10012 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
10014 std::vector<int> candidates1(1);
10015 int offset1(m1Desc->getNumberOfNodes());
10016 int offset2(offset1+m2Desc->getNumberOfNodes());
10017 for(int i=0;i<nDescCell1;i++) // for all edges in the first mesh
10019 std::vector<int> candidates2; // edges of mesh2 candidate for intersection
10020 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10021 if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
10023 std::map<INTERP_KERNEL::Node *,int> map1,map2;
10024 // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
10025 INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
10027 INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
10028 // 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
10029 // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
10030 std::set<INTERP_KERNEL::Node *> nodes;
10031 pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
10032 std::size_t szz(nodes.size());
10033 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
10034 std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
10035 for(std::size_t iii=0;iii<szz;iii++,itt++)
10036 { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
10037 // end of protection
10038 // Performs egde cutting:
10039 pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes);
10044 intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
10049 * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
10050 * It builds the descending connectivity of the two meshes, and then using a binary tree
10051 * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
10052 * Documentation about parameters colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
10054 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
10055 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
10056 MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
10057 std::vector<double>& addCoo,
10058 MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
10060 // Build desc connectivity
10061 desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
10062 desc2=DataArrayInt::New();
10063 descIndx2=DataArrayInt::New();
10064 revDesc2=DataArrayInt::New();
10065 revDescIndx2=DataArrayInt::New();
10066 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
10067 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
10068 m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
10069 m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
10070 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
10071 std::map<int,int> notUsedMap;
10072 Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap);
10073 m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
10074 m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
10078 * This method performs the 2nd step of Partition of 2D mesh.
10079 * This method has 4 inputs :
10080 * - a mesh 'm1' with meshDim==1 and a SpaceDim==2
10081 * - a mesh 'm2' with meshDim==1 and a SpaceDim==2
10082 * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
10083 * 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'
10084 * Nodes end up lying consecutively on a cutted edge.
10085 * \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.
10086 * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
10087 * \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.
10088 * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
10089 * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
10091 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
10092 const std::vector<double>& addCoo,
10093 const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
10095 int offset1=m1->getNumberOfNodes();
10096 int ncell=m2->getNumberOfCells();
10097 const int *c=m2->getNodalConnectivity()->getConstPointer();
10098 const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
10099 const double *coo=m2->getCoords()->getConstPointer();
10100 const double *cooBis=m1->getCoords()->getConstPointer();
10101 int offset2=offset1+m2->getNumberOfNodes();
10102 intersectEdge.resize(ncell);
10103 for(int i=0;i<ncell;i++,cI++)
10105 const std::vector<int>& divs=subDiv[i];
10106 int nnode=cI[1]-cI[0]-1;
10107 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
10108 std::map<INTERP_KERNEL::Node *, int> mapp22;
10109 for(int j=0;j<nnode;j++)
10111 INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
10112 int nnid=c[(*cI)+j+1];
10113 mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
10114 mapp22[nn]=nnid+offset1;
10116 INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
10117 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
10118 ((*it).second.first)->decrRef();
10119 std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
10120 std::map<INTERP_KERNEL::Node *,int> mapp3;
10121 for(std::size_t j=0;j<divs.size();j++)
10124 INTERP_KERNEL::Node *tmp=0;
10126 tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
10127 else if(id<offset2)
10128 tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
10130 tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
10134 e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
10135 for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
10142 * 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).
10143 * 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
10144 * with a plane. The result will be put in 'cut3DSuf' out parameter.
10145 * \param [in] cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
10146 * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
10147 * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
10148 * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
10149 * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
10150 * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
10151 * \param [in] desc is the descending connectivity 3DSurf->3DCurve
10152 * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
10153 * \param [out] cut3DSuf input/output param.
10155 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
10156 const int *nodal3DCurve, const int *nodalIndx3DCurve,
10157 const int *desc, const int *descIndx,
10158 std::vector< std::pair<int,int> >& cut3DSurf)
10160 std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
10161 int nbOf3DSurfCell=(int)cut3DSurf.size();
10162 for(int i=0;i<nbOf3DSurfCell;i++)
10164 std::vector<int> res;
10165 int offset=descIndx[i];
10166 int nbOfSeg=descIndx[i+1]-offset;
10167 for(int j=0;j<nbOfSeg;j++)
10169 int edgeId=desc[offset+j];
10170 int status=cut3DCurve[edgeId];
10174 res.push_back(status);
10177 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
10178 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
10186 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10192 std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
10193 std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
10196 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10200 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
10205 {// case when plane is on a multi colinear edge of a polyhedron
10206 if((int)res.size()==2*nbOfSeg)
10208 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
10211 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
10218 * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
10219 * 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).
10220 * 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
10221 * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
10222 * \param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
10223 * \param desc is the descending connectivity 3D->3DSurf
10224 * \param descIndx is the descending connectivity index 3D->3DSurf
10226 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
10227 const int *desc, const int *descIndx,
10228 DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
10230 checkFullyDefined();
10231 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10232 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
10233 const int *nodal3D=_nodal_connec->getConstPointer();
10234 const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
10235 int nbOfCells=getNumberOfCells();
10236 for(int i=0;i<nbOfCells;i++)
10238 std::map<int, std::set<int> > m;
10239 int offset=descIndx[i];
10240 int nbOfFaces=descIndx[i+1]-offset;
10243 for(int j=0;j<nbOfFaces;j++)
10245 const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
10246 if(p.first!=-1 && p.second!=-1)
10250 start=p.first; end=p.second;
10251 m[p.first].insert(p.second);
10252 m[p.second].insert(p.first);
10256 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
10257 int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
10258 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
10259 INTERP_KERNEL::NormalizedCellType cmsId;
10260 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
10261 start=tmp[0]; end=tmp[nbOfNodesSon-1];
10262 for(unsigned k=0;k<nbOfNodesSon;k++)
10264 m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
10265 m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
10272 std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
10276 std::map<int, std::set<int> >::const_iterator it=m.find(start);
10277 const std::set<int>& s=(*it).second;
10278 std::set<int> s2; s2.insert(prev);
10280 std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
10283 int val=*s3.begin();
10284 conn.push_back(start);
10291 conn.push_back(end);
10294 nodalRes->insertAtTheEnd(conn.begin(),conn.end());
10295 nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
10296 cellIds->pushBackSilent(i);
10302 * 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
10303 * 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
10304 * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
10305 * 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
10306 * 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.
10308 * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
10310 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
10312 std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
10315 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
10316 if(cm.getDimension()==2)
10318 const int *node=nodalConnBg+1;
10319 int startNode=*node++;
10320 double refX=coords[2*startNode];
10321 for(;node!=nodalConnEnd;node++)
10323 if(coords[2*(*node)]<refX)
10326 refX=coords[2*startNode];
10329 std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
10333 double angle0=-M_PI/2;
10338 double angleNext=0.;
10339 while(nextNode!=startNode)
10343 for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
10345 if(*node!=tmpOut.back() && *node!=prevNode)
10347 tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
10348 double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
10353 res=angle0-angleM+2.*M_PI;
10362 if(nextNode!=startNode)
10364 angle0=angleNext-M_PI;
10367 prevNode=tmpOut.back();
10368 tmpOut.push_back(nextNode);
10371 std::vector<int> tmp3(2*(sz-1));
10372 std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
10373 std::copy(nodalConnBg+1,nodalConnEnd,it);
10374 if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
10376 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10379 if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
10381 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10386 nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
10387 nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
10392 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10395 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10399 * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
10400 * 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.
10402 * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
10403 * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
10404 * \param [in,out] arr array in which the remove operation will be done.
10405 * \param [in,out] arrIndx array in the remove operation will modify
10406 * \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])
10407 * \return true if \b arr and \b arrIndx have been modified, false if not.
10409 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
10411 if(!arrIndx || !arr)
10412 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
10413 if(offsetForRemoval<0)
10414 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
10415 std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
10416 int nbOfGrps=arrIndx->getNumberOfTuples()-1;
10417 int *arrIPtr=arrIndx->getPointer();
10419 int previousArrI=0;
10420 const int *arrPtr=arr->getConstPointer();
10421 std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
10422 for(int i=0;i<nbOfGrps;i++,arrIPtr++)
10424 if(*arrIPtr-previousArrI>offsetForRemoval)
10426 for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
10428 if(s.find(*work)==s.end())
10429 arrOut.push_back(*work);
10432 previousArrI=*arrIPtr;
10433 *arrIPtr=(int)arrOut.size();
10435 if(arr->getNumberOfTuples()==(int)arrOut.size())
10437 arr->alloc((int)arrOut.size(),1);
10438 std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
10443 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10444 * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
10445 * The selection of extraction is done standardly in new2old format.
10446 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10448 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10449 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10450 * \param [in] arrIn arr origin array from which the extraction will be done.
10451 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10452 * \param [out] arrOut the resulting array
10453 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10454 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
10456 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10457 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10459 if(!arrIn || !arrIndxIn)
10460 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
10461 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10462 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10463 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
10464 std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
10465 const int *arrInPtr=arrIn->getConstPointer();
10466 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10467 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10469 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10470 int maxSizeOfArr=arrIn->getNumberOfTuples();
10471 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10472 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10473 arrIo->alloc((int)(sz+1),1);
10474 const int *idsIt=idsOfSelectBg;
10475 int *work=arrIo->getPointer();
10478 for(std::size_t i=0;i<sz;i++,work++,idsIt++)
10480 if(*idsIt>=0 && *idsIt<nbOfGrps)
10481 lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
10484 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10485 throw INTERP_KERNEL::Exception(oss.str().c_str());
10491 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
10492 oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
10493 throw INTERP_KERNEL::Exception(oss.str().c_str());
10496 arro->alloc(lgth,1);
10497 work=arro->getPointer();
10498 idsIt=idsOfSelectBg;
10499 for(std::size_t i=0;i<sz;i++,idsIt++)
10501 if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
10502 work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
10505 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
10506 oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10507 throw INTERP_KERNEL::Exception(oss.str().c_str());
10510 arrOut=arro.retn();
10511 arrIndexOut=arrIo.retn();
10515 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10516 * 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 ).
10517 * The selection of extraction is done standardly in new2old format.
10518 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10520 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10521 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10522 * \param [in] arrIn arr origin array from which the extraction will be done.
10523 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10524 * \param [out] arrOut the resulting array
10525 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10526 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
10528 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10529 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10531 if(!arrIn || !arrIndxIn)
10532 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
10533 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10534 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10535 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
10536 int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
10537 const int *arrInPtr=arrIn->getConstPointer();
10538 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10539 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10541 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10542 int maxSizeOfArr=arrIn->getNumberOfTuples();
10543 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10544 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10545 arrIo->alloc((int)(sz+1),1);
10546 int idsIt=idsOfSelectStart;
10547 int *work=arrIo->getPointer();
10550 for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
10552 if(idsIt>=0 && idsIt<nbOfGrps)
10553 lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
10556 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10557 throw INTERP_KERNEL::Exception(oss.str().c_str());
10563 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
10564 oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
10565 throw INTERP_KERNEL::Exception(oss.str().c_str());
10568 arro->alloc(lgth,1);
10569 work=arro->getPointer();
10570 idsIt=idsOfSelectStart;
10571 for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
10573 if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
10574 work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
10577 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
10578 oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10579 throw INTERP_KERNEL::Exception(oss.str().c_str());
10582 arrOut=arro.retn();
10583 arrIndexOut=arrIo.retn();
10587 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10588 * 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
10589 * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
10590 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
10592 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10593 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10594 * \param [in] arrIn arr origin array from which the extraction will be done.
10595 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10596 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
10597 * \param [in] srcArrIndex index array of \b srcArr
10598 * \param [out] arrOut the resulting array
10599 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10601 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
10603 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10604 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
10605 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10607 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10608 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
10609 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10610 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10611 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10612 std::vector<bool> v(nbOfTuples,true);
10614 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10615 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10616 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10618 if(*it>=0 && *it<nbOfTuples)
10621 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
10625 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
10626 throw INTERP_KERNEL::Exception(oss.str().c_str());
10629 srcArrIndexPtr=srcArrIndex->getConstPointer();
10630 arrIo->alloc(nbOfTuples+1,1);
10631 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
10632 const int *arrInPtr=arrIn->getConstPointer();
10633 const int *srcArrPtr=srcArr->getConstPointer();
10634 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
10635 int *arroPtr=arro->getPointer();
10636 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
10640 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
10641 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
10645 std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
10646 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
10647 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
10650 arrOut=arro.retn();
10651 arrIndexOut=arrIo.retn();
10655 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10656 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
10658 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10659 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10660 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
10661 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10662 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
10663 * \param [in] srcArrIndex index array of \b srcArr
10665 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
10667 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
10668 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
10670 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10671 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
10672 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10673 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10674 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10675 int *arrInOutPtr=arrInOut->getPointer();
10676 const int *srcArrPtr=srcArr->getConstPointer();
10677 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10679 if(*it>=0 && *it<nbOfTuples)
10681 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
10682 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
10685 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] !";
10686 throw INTERP_KERNEL::Exception(oss.str().c_str());
10691 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
10692 throw INTERP_KERNEL::Exception(oss.str().c_str());
10698 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
10699 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
10700 * 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]].
10701 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
10702 * A negative value in \b arrIn means that it is ignored.
10703 * 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.
10705 * \param [in] arrIn arr origin array from which the extraction will be done.
10706 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10707 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
10708 * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
10710 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
10712 int seed=0,nbOfDepthPeelingPerformed=0;
10713 return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
10717 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
10718 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
10719 * 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]].
10720 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
10721 * A negative value in \b arrIn means that it is ignored.
10722 * 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.
10723 * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
10724 * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
10725 * \param [in] arrIn arr origin array from which the extraction will be done.
10726 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10727 * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
10728 * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
10729 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
10730 * \sa MEDCouplingUMesh::partitionBySpreadZone
10732 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
10734 nbOfDepthPeelingPerformed=0;
10736 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
10737 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10740 DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
10744 std::vector<bool> fetched(nbOfTuples,false);
10745 return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
10748 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
10750 nbOfDepthPeelingPerformed=0;
10751 if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
10752 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
10753 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10754 std::vector<bool> fetched2(nbOfTuples,false);
10756 for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
10758 if(*seedElt>=0 && *seedElt<nbOfTuples)
10759 { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
10761 { 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()); }
10763 const int *arrInPtr=arrIn->getConstPointer();
10764 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10765 int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
10766 std::vector<int> idsToFetch1(seedBg,seedEnd);
10767 std::vector<int> idsToFetch2;
10768 std::vector<int> *idsToFetch=&idsToFetch1;
10769 std::vector<int> *idsToFetchOther=&idsToFetch2;
10770 while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
10772 for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
10773 for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
10775 { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
10776 std::swap(idsToFetch,idsToFetchOther);
10777 idsToFetchOther->clear();
10778 nbOfDepthPeelingPerformed++;
10780 int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
10782 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
10783 int *retPtr=ret->getPointer();
10784 for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
10791 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10792 * 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
10793 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
10794 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
10796 * \param [in] start begin of set of ids of the input extraction (included)
10797 * \param [in] end end of set of ids of the input extraction (excluded)
10798 * \param [in] step step of the set of ids in range mode.
10799 * \param [in] arrIn arr origin array from which the extraction will be done.
10800 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10801 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
10802 * \param [in] srcArrIndex index array of \b srcArr
10803 * \param [out] arrOut the resulting array
10804 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10806 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
10808 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10809 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
10810 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10812 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10813 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
10814 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10815 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10816 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10818 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10819 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10820 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
10822 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
10824 if(it>=0 && it<nbOfTuples)
10825 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
10828 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
10829 throw INTERP_KERNEL::Exception(oss.str().c_str());
10832 srcArrIndexPtr=srcArrIndex->getConstPointer();
10833 arrIo->alloc(nbOfTuples+1,1);
10834 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
10835 const int *arrInPtr=arrIn->getConstPointer();
10836 const int *srcArrPtr=srcArr->getConstPointer();
10837 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
10838 int *arroPtr=arro->getPointer();
10839 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
10841 int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
10844 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
10845 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
10849 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
10850 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
10853 arrOut=arro.retn();
10854 arrIndexOut=arrIo.retn();
10858 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10859 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
10861 * \param [in] start begin of set of ids of the input extraction (included)
10862 * \param [in] end end of set of ids of the input extraction (excluded)
10863 * \param [in] step step of the set of ids in range mode.
10864 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
10865 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10866 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
10867 * \param [in] srcArrIndex index array of \b srcArr
10869 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
10871 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
10872 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
10874 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10875 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
10876 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10877 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10878 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10879 int *arrInOutPtr=arrInOut->getPointer();
10880 const int *srcArrPtr=srcArr->getConstPointer();
10881 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
10883 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
10885 if(it>=0 && it<nbOfTuples)
10887 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
10888 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
10891 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
10892 throw INTERP_KERNEL::Exception(oss.str().c_str());
10897 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
10898 throw INTERP_KERNEL::Exception(oss.str().c_str());
10904 * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
10905 * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
10906 * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
10907 * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
10908 * The sum of measure field of returned mesh is equal to the sum of measure field of this.
10910 * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
10912 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
10914 checkFullyDefined();
10915 int mdim=getMeshDimension();
10916 int spaceDim=getSpaceDimension();
10918 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
10919 std::vector<DataArrayInt *> partition=partitionBySpreadZone();
10920 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
10921 std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
10922 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
10923 ret->setCoords(getCoords());
10924 ret->allocateCells((int)partition.size());
10926 for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
10928 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
10929 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
10933 cell=tmp->buildUnionOf2DMesh();
10936 cell=tmp->buildUnionOf3DMesh();
10939 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
10942 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
10945 ret->finishInsertingCells();
10950 * This method partitions \b this into contiguous zone.
10951 * This method only needs a well defined connectivity. Coordinates are not considered here.
10952 * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
10954 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
10956 int nbOfCellsCur=getNumberOfCells();
10957 std::vector<DataArrayInt *> ret;
10958 if(nbOfCellsCur<=0)
10960 DataArrayInt *neigh=0,*neighI=0;
10961 computeNeighborsOfCells(neigh,neighI);
10962 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
10963 std::vector<bool> fetchedCells(nbOfCellsCur,false);
10964 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
10966 while(seed<nbOfCellsCur)
10968 int nbOfPeelPerformed=0;
10969 ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
10970 seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
10972 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
10973 ret.push_back((*it).retn());
10978 * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
10979 * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
10981 * \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.
10982 * \return a newly allocated DataArrayInt to be managed by the caller.
10983 * \throw In case of \a code has not the right format (typically of size 3*n)
10985 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
10987 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
10988 std::size_t nb=code.size()/3;
10989 if(code.size()%3!=0)
10990 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
10991 ret->alloc((int)nb,2);
10992 int *retPtr=ret->getPointer();
10993 for(std::size_t i=0;i<nb;i++,retPtr+=2)
10995 retPtr[0]=code[3*i+2];
10996 retPtr[1]=code[3*i+2]+code[3*i+1];
11002 * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
11003 * All cells in \a this are expected to be linear 3D cells.
11004 * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
11005 * It leads to an increase to number of cells.
11006 * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
11007 * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints
11008 * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
11010 * \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.
11011 * For all other cells, the splitting policy will be ignored.
11012 * \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.
11013 * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
11014 * an id of old cell producing it. The caller is to delete this array using
11015 * decrRef() as it is no more needed.
11016 * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
11018 * \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
11019 * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
11021 * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
11022 * \throw If \a this is not fully constituted with linear 3D cells.
11023 * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
11025 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
11027 INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
11028 checkConnectivityFullyDefined();
11029 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
11030 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
11031 int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
11032 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
11033 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
11034 int *retPt(ret->getPointer());
11035 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
11036 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
11037 const int *oldc(_nodal_connec->begin());
11038 const int *oldci(_nodal_connec_index->begin());
11039 const double *coords(_coords->begin());
11040 for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
11042 std::vector<int> a; std::vector<double> b;
11043 INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
11044 std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
11045 const int *aa(&a[0]);
11048 for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
11050 *it=(-(*(it))-1+nbNodes);
11051 addPts->insertAtTheEnd(b.begin(),b.end());
11052 nbNodes+=(int)b.size()/3;
11054 for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
11055 newConn->insertAtTheEnd(aa,aa+4);
11057 if(!addPts->empty())
11059 addPts->rearrange(3);
11060 nbOfAdditionalPoints=addPts->getNumberOfTuples();
11061 addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
11062 ret0->setCoords(addPts);
11066 nbOfAdditionalPoints=0;
11067 ret0->setCoords(getCoords());
11069 ret0->setNodalConnectivity(newConn);
11071 ret->computeOffsets2();
11072 n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
11073 return ret0.retn();
11077 * 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).
11079 * \sa MEDCouplingUMesh::split2DCells
11081 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
11083 checkConnectivityFullyDefined();
11084 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
11085 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11086 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11087 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11088 int prevPosOfCi(ciPtr[0]);
11089 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11091 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
11092 *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
11093 for(int j=0;j<sz;j++)
11095 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
11096 for(int k=0;k<sz2;k++)
11097 *cPtr++=subPtr[offset2+k];
11099 *cPtr++=oldConn[prevPosOfCi+j+2];
11102 prevPosOfCi=ciPtr[1];
11103 ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11106 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
11107 _nodal_connec->decrRef();
11108 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
11111 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11117 int ret(nodesCnter++);
11119 e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
11120 addCoo.insertAtTheEnd(newPt,newPt+2);
11127 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)
11130 int trueStart(start>=0?start:nbOfEdges+start);
11131 tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
11132 newConnOfCell->insertAtTheEnd(tmp,tmp+3);
11137 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11138 InternalAddPoint(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
11139 middles.push_back(tmp3+offset);
11142 middles.push_back(connBg[trueStart+nbOfEdges]);
11146 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)
11148 int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
11149 newConnOfCell->pushBackSilent(tmpEnd);
11154 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11155 InternalAddPoint(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11156 middles.push_back(tmp3+offset);
11159 middles.push_back(connBg[start+nbOfEdges]);
11163 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)
11169 int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
11170 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11171 InternalAddPoint(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11172 middles.push_back(tmp3+offset);
11175 middles.push_back(connBg[start+nbOfEdges]);
11182 * 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 ) .
11183 * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
11185 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
11187 std::size_t sz(std::distance(connBg,connEnd));
11188 if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
11189 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
11191 INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
11192 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
11193 unsigned nbs(cm.getNumberOfSons2(connBg+1,sz)),nbOfHit(0);
11194 int posBaseElt(0),posEndElt(0),nbOfTurn(0);
11195 INTERP_KERNEL::NormalizedCellType typeOfSon;
11196 std::vector<int> middles;
11198 for(;nbOfHit<nbs;nbOfTurn++)
11200 cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
11201 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
11202 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11205 unsigned endI(nbs-nbOfHit);
11206 for(unsigned i=0;i<endI;i++)
11208 cm.fillSonCellNodalConnectivity2(posBaseElt+(int)i+1,connBg+1,sz,tmpConn,typeOfSon);
11209 INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11210 INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11211 bool isColinear(eint->areColinears());
11223 {//look if the first edge of cell is not colinear with last edges in this case the start of nodal connectivity is shifted back
11224 unsigned endII(nbs-nbOfHit-1);//warning nbOfHit can be modified, so put end condition in a variable.
11225 for(unsigned ii=0;ii<endII;ii++)
11227 cm.fillSonCellNodalConnectivity2(nbs-ii-1,connBg+1,sz,tmpConn,typeOfSon);
11228 eCand=MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m);
11229 eint=INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand);
11230 isColinear=eint->areColinears();
11246 //push [posBaseElt,posEndElt) in newConnOfCell using e
11248 EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11249 else if(nbOfHit!=nbs)
11250 EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11252 EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11253 posBaseElt=posEndElt;
11256 if(!middles.empty())
11257 newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
11262 * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
11264 * \return int - the number of new nodes created.
11265 * \sa MEDCouplingUMesh::split2DCells
11267 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
11270 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
11271 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11272 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
11273 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11274 const int *midPtr(mid->begin()),*midIPtr(midI->begin());
11275 const double *oldCoordsPtr(getCoords()->begin());
11276 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11277 int prevPosOfCi(ciPtr[0]);
11278 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11280 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
11281 for(int j=0;j<sz;j++)
11282 { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
11283 *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
11284 for(int j=0;j<sz;j++)//loop over subedges of oldConn
11286 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
11290 cPtr[1]=oldConn[prevPosOfCi+2+j];
11291 cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
11294 std::vector<INTERP_KERNEL::Node *> ns(3);
11295 ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
11296 ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
11297 ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
11298 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
11299 for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
11301 cPtr[1]=subPtr[offset2+k];
11302 cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
11304 int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
11306 { cPtr[1]=tmpEnd; }
11307 cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
11309 prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
11310 ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11313 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
11314 _nodal_connec->decrRef();
11315 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
11316 addCoo->rearrange(2);
11317 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
11319 return addCoo->getNumberOfTuples();
11322 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
11323 _own_cell(true),_cell_id(-1),_nb_cell(0)
11328 _nb_cell=mesh->getNumberOfCells();
11332 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
11340 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
11341 _own_cell(false),_cell_id(bg-1),
11348 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
11351 if(_cell_id<_nb_cell)
11360 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
11366 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
11368 return new MEDCouplingUMeshCellByTypeIterator(_mesh);
11371 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
11377 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
11385 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
11391 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
11396 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
11401 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
11403 return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
11406 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
11411 _nb_cell=mesh->getNumberOfCells();
11415 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
11422 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
11424 const int *c=_mesh->getNodalConnectivity()->getConstPointer();
11425 const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
11426 if(_cell_id<_nb_cell)
11428 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
11429 int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
11430 int startId=_cell_id;
11431 _cell_id+=nbOfElems;
11432 return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
11438 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
11442 _conn=mesh->getNodalConnectivity()->getPointer();
11443 _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
11447 void MEDCouplingUMeshCell::next()
11449 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11454 _conn_lgth=_conn_indx[1]-_conn_indx[0];
11457 std::string MEDCouplingUMeshCell::repr() const
11459 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11461 std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
11463 std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
11467 return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
11470 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
11472 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11473 return (INTERP_KERNEL::NormalizedCellType)_conn[0];
11475 return INTERP_KERNEL::NORM_ERROR;
11478 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
11481 if(_conn_lgth!=NOTICABLE_FIRST_VAL)