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 * Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
2502 * 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
2505 void MEDCouplingUMesh::renumberNodesInConn(const std::map<int,int>& newNodeNumbersO2N)
2507 checkConnectivityFullyDefined();
2508 int *conn(getNodalConnectivity()->getPointer());
2509 const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2510 int nbOfCells=getNumberOfCells();
2511 for(int i=0;i<nbOfCells;i++)
2512 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2514 int& node=conn[iconn];
2515 if(node>=0)//avoid polyhedron separator
2517 std::map<int,int>::const_iterator it(newNodeNumbersO2N.find(node));
2518 if(it!=newNodeNumbersO2N.end())
2524 std::ostringstream oss; oss << "MEDCouplingUMesh::renumberNodesInConn(map) : presence in connectivity for cell #" << i << " of node #" << node << " : Not in map !";
2525 throw INTERP_KERNEL::Exception(oss.str().c_str());
2529 _nodal_connec->declareAsNew();
2534 * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2535 * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2536 * This method is a generalization of shiftNodeNumbersInConn().
2537 * \warning This method performs no check of validity of new ids. **Use it with care !**
2538 * \param [in] newNodeNumbersO2N - a permutation array, of length \a
2539 * this->getNumberOfNodes(), in "Old to New" mode.
2540 * See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2541 * \throw If the nodal connectivity of cells is not defined.
2543 * \if ENABLE_EXAMPLES
2544 * \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2545 * \ref py_mcumesh_renumberNodesInConn "Here is a Python example".
2548 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2550 checkConnectivityFullyDefined();
2551 int *conn=getNodalConnectivity()->getPointer();
2552 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2553 int nbOfCells=getNumberOfCells();
2554 for(int i=0;i<nbOfCells;i++)
2555 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2557 int& node=conn[iconn];
2558 if(node>=0)//avoid polyhedron separator
2560 node=newNodeNumbersO2N[node];
2563 _nodal_connec->declareAsNew();
2568 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2569 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2570 * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2572 * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2574 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2576 checkConnectivityFullyDefined();
2577 int *conn=getNodalConnectivity()->getPointer();
2578 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2579 int nbOfCells=getNumberOfCells();
2580 for(int i=0;i<nbOfCells;i++)
2581 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2583 int& node=conn[iconn];
2584 if(node>=0)//avoid polyhedron separator
2589 _nodal_connec->declareAsNew();
2594 * This method operates a modification of the connectivity in \b this.
2595 * 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.
2596 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2597 * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2598 * 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
2599 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2600 * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2602 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2603 * As an another consequense after the call of this method \b this can be transiently non cohrent.
2605 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2606 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2607 * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ).
2609 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2611 checkConnectivityFullyDefined();
2612 std::map<int,int> m;
2614 for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2616 int *conn=getNodalConnectivity()->getPointer();
2617 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2618 int nbOfCells=getNumberOfCells();
2619 for(int i=0;i<nbOfCells;i++)
2620 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2622 int& node=conn[iconn];
2623 if(node>=0)//avoid polyhedron separator
2625 std::map<int,int>::iterator it=m.find(node);
2634 * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2636 * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2637 * After the call of this method the number of cells remains the same as before.
2639 * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2640 * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2641 * be strictly in [0;this->getNumberOfCells()).
2643 * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2644 * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2645 * should be contained in[0;this->getNumberOfCells()).
2647 * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2649 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2651 checkConnectivityFullyDefined();
2652 int nbCells=getNumberOfCells();
2653 const int *array=old2NewBg;
2655 array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2657 const int *conn=_nodal_connec->getConstPointer();
2658 const int *connI=_nodal_connec_index->getConstPointer();
2659 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2660 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2661 const int *n2oPtr=n2o->begin();
2662 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2663 newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2664 newConn->copyStringInfoFrom(*_nodal_connec);
2665 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2666 newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2667 newConnI->copyStringInfoFrom(*_nodal_connec_index);
2669 int *newC=newConn->getPointer();
2670 int *newCI=newConnI->getPointer();
2673 for(int i=0;i<nbCells;i++)
2676 int nbOfElts=connI[pos+1]-connI[pos];
2677 newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2682 setConnectivity(newConn,newConnI);
2684 free(const_cast<int *>(array));
2688 * Finds cells whose bounding boxes intersect a given bounding box.
2689 * \param [in] bbox - an array defining the bounding box via coordinates of its
2690 * extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2692 * \param [in] eps - a factor used to increase size of the bounding box of cell
2693 * before comparing it with \a bbox. This factor is multiplied by the maximal
2694 * extent of the bounding box of cell to produce an addition to this bounding box.
2695 * \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2696 * cells. The caller is to delete this array using decrRef() as it is no more
2698 * \throw If the coordinates array is not set.
2699 * \throw If the nodal connectivity of cells is not defined.
2701 * \if ENABLE_EXAMPLES
2702 * \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2703 * \ref py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2706 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2708 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2709 if(getMeshDimension()==-1)
2711 elems->pushBackSilent(0);
2712 return elems.retn();
2714 int dim=getSpaceDimension();
2715 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2716 const int* conn = getNodalConnectivity()->getConstPointer();
2717 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2718 const double* coords = getCoords()->getConstPointer();
2719 int nbOfCells=getNumberOfCells();
2720 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2722 for (int i=0; i<dim; i++)
2724 elem_bb[i*2]=std::numeric_limits<double>::max();
2725 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2728 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2730 int node= conn[inode];
2731 if(node>=0)//avoid polyhedron separator
2733 for (int idim=0; idim<dim; idim++)
2735 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2737 elem_bb[idim*2] = coords[node*dim+idim] ;
2739 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2741 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2746 if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2747 elems->pushBackSilent(ielem);
2749 return elems.retn();
2753 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2754 * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2755 * added in 'elems' parameter.
2757 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2759 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2760 if(getMeshDimension()==-1)
2762 elems->pushBackSilent(0);
2763 return elems.retn();
2765 int dim=getSpaceDimension();
2766 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2767 const int* conn = getNodalConnectivity()->getConstPointer();
2768 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2769 const double* coords = getCoords()->getConstPointer();
2770 int nbOfCells=getNumberOfCells();
2771 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2773 for (int i=0; i<dim; i++)
2775 elem_bb[i*2]=std::numeric_limits<double>::max();
2776 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2779 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2781 int node= conn[inode];
2782 if(node>=0)//avoid polyhedron separator
2784 for (int idim=0; idim<dim; idim++)
2786 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2788 elem_bb[idim*2] = coords[node*dim+idim] ;
2790 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2792 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2797 if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2798 elems->pushBackSilent(ielem);
2800 return elems.retn();
2804 * Returns a type of a cell by its id.
2805 * \param [in] cellId - the id of the cell of interest.
2806 * \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2807 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2809 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2811 const int *ptI=_nodal_connec_index->getConstPointer();
2812 const int *pt=_nodal_connec->getConstPointer();
2813 if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2814 return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2817 std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2818 throw INTERP_KERNEL::Exception(oss.str().c_str());
2823 * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2824 * This method does not throw exception if geometric type \a type is not in \a this.
2825 * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2826 * The coordinates array is not considered here.
2828 * \param [in] type the geometric type
2829 * \return cell ids in this having geometric type \a type.
2831 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2834 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2836 checkConnectivityFullyDefined();
2837 int nbCells=getNumberOfCells();
2838 int mdim=getMeshDimension();
2839 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2840 if(mdim!=(int)cm.getDimension())
2841 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2842 const int *ptI=_nodal_connec_index->getConstPointer();
2843 const int *pt=_nodal_connec->getConstPointer();
2844 for(int i=0;i<nbCells;i++)
2846 if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2847 ret->pushBackSilent(i);
2853 * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2855 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2857 const int *ptI=_nodal_connec_index->getConstPointer();
2858 const int *pt=_nodal_connec->getConstPointer();
2859 int nbOfCells=getNumberOfCells();
2861 for(int i=0;i<nbOfCells;i++)
2862 if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2868 * Returns the nodal connectivity of a given cell.
2869 * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2870 * all returned node ids can be used in getCoordinatesOfNode().
2871 * \param [in] cellId - an id of the cell of interest.
2872 * \param [in,out] conn - a vector where the node ids are appended. It is not
2873 * cleared before the appending.
2874 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2876 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2878 const int *ptI=_nodal_connec_index->getConstPointer();
2879 const int *pt=_nodal_connec->getConstPointer();
2880 for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2885 std::string MEDCouplingUMesh::simpleRepr() const
2887 static const char msg0[]="No coordinates specified !";
2888 std::ostringstream ret;
2889 ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2890 ret << "Description of mesh : \"" << getDescription() << "\"\n";
2892 double tt=getTime(tmpp1,tmpp2);
2893 ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2894 ret << "Iteration : " << tmpp1 << " Order : " << tmpp2 << "\n";
2896 { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2898 { ret << " Mesh dimension has not been set or is invalid !"; }
2901 const int spaceDim=getSpaceDimension();
2902 ret << spaceDim << "\nInfo attached on space dimension : ";
2903 for(int i=0;i<spaceDim;i++)
2904 ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2908 ret << msg0 << "\n";
2909 ret << "Number of nodes : ";
2911 ret << getNumberOfNodes() << "\n";
2913 ret << msg0 << "\n";
2914 ret << "Number of cells : ";
2915 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2916 ret << getNumberOfCells() << "\n";
2918 ret << "No connectivity specified !" << "\n";
2919 ret << "Cell types present : ";
2920 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2922 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2923 ret << cm.getRepr() << " ";
2929 std::string MEDCouplingUMesh::advancedRepr() const
2931 std::ostringstream ret;
2932 ret << simpleRepr();
2933 ret << "\nCoordinates array : \n___________________\n\n";
2935 _coords->reprWithoutNameStream(ret);
2937 ret << "No array set !\n";
2938 ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2939 reprConnectivityOfThisLL(ret);
2944 * This method returns a C++ code that is a dump of \a this.
2945 * This method will throw if this is not fully defined.
2947 std::string MEDCouplingUMesh::cppRepr() const
2949 static const char coordsName[]="coords";
2950 static const char connName[]="conn";
2951 static const char connIName[]="connI";
2952 checkFullyDefined();
2953 std::ostringstream ret; ret << "// coordinates" << std::endl;
2954 _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2955 _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2956 _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2957 ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2958 ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2959 ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2960 ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2964 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2966 std::ostringstream ret;
2967 reprConnectivityOfThisLL(ret);
2972 * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
2973 * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2974 * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2977 * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2978 * 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
2979 * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2981 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
2983 int mdim=getMeshDimension();
2985 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2986 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
2987 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
2988 bool needToCpyCT=true;
2991 tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2999 if(!_nodal_connec_index)
3001 tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
3006 tmp2=_nodal_connec_index;
3009 ret->setConnectivity(tmp1,tmp2,false);
3014 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
3015 ret->setCoords(coords);
3018 ret->setCoords(_coords);
3022 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
3024 if(_nodal_connec!=0 && _nodal_connec_index!=0)
3026 int nbOfCells=getNumberOfCells();
3027 const int *c=_nodal_connec->getConstPointer();
3028 const int *ci=_nodal_connec_index->getConstPointer();
3029 for(int i=0;i<nbOfCells;i++)
3031 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3032 stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3033 std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3038 stream << "Connectivity not defined !\n";
3041 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3043 const int *ptI=_nodal_connec_index->getConstPointer();
3044 const int *pt=_nodal_connec->getConstPointer();
3045 if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3046 return ptI[cellId+1]-ptI[cellId]-1;
3048 return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3052 * Returns types of cells of the specified part of \a this mesh.
3053 * This method avoids computing sub-mesh explicitely to get its types.
3054 * \param [in] begin - an array of cell ids of interest.
3055 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3056 * \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3057 * describing the cell types.
3058 * \throw If the coordinates array is not set.
3059 * \throw If the nodal connectivity of cells is not defined.
3060 * \sa getAllGeoTypes()
3062 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3064 checkFullyDefined();
3065 std::set<INTERP_KERNEL::NormalizedCellType> ret;
3066 const int *conn=_nodal_connec->getConstPointer();
3067 const int *connIndex=_nodal_connec_index->getConstPointer();
3068 for(const int *w=begin;w!=end;w++)
3069 ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3074 * Defines the nodal connectivity using given connectivity arrays. Optionally updates
3075 * a set of types of cells constituting \a this mesh.
3076 * This method is for advanced users having prepared their connectivity before. For
3077 * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3078 * \param [in] conn - the nodal connectivity array.
3079 * \param [in] connIndex - the nodal connectivity index array.
3080 * \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3083 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3085 DataArrayInt::SetArrayIn(conn,_nodal_connec);
3086 DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3087 if(isComputingTypes)
3093 * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
3094 * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3096 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3097 _nodal_connec(0),_nodal_connec_index(0),
3098 _types(other._types)
3100 if(other._nodal_connec)
3101 _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3102 if(other._nodal_connec_index)
3103 _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3106 MEDCouplingUMesh::~MEDCouplingUMesh()
3109 _nodal_connec->decrRef();
3110 if(_nodal_connec_index)
3111 _nodal_connec_index->decrRef();
3115 * Recomputes a set of cell types of \a this mesh. For more info see
3116 * \ref MEDCouplingUMeshNodalConnectivity.
3118 void MEDCouplingUMesh::computeTypes()
3120 if(_nodal_connec && _nodal_connec_index)
3123 const int *conn=_nodal_connec->getConstPointer();
3124 const int *connIndex=_nodal_connec_index->getConstPointer();
3125 int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
3127 for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
3128 _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
3133 * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3135 void MEDCouplingUMesh::checkFullyDefined() const
3137 if(!_nodal_connec_index || !_nodal_connec || !_coords)
3138 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3142 * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3144 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3146 if(!_nodal_connec_index || !_nodal_connec)
3147 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3151 * Returns a number of cells constituting \a this mesh.
3152 * \return int - the number of cells in \a this mesh.
3153 * \throw If the nodal connectivity of cells is not defined.
3155 int MEDCouplingUMesh::getNumberOfCells() const
3157 if(_nodal_connec_index)
3158 return _nodal_connec_index->getNumberOfTuples()-1;
3163 throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3167 * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3168 * mesh. For more info see \ref MEDCouplingMeshesPage.
3169 * \return int - the dimension of \a this mesh.
3170 * \throw If the mesh dimension is not defined using setMeshDimension().
3172 int MEDCouplingUMesh::getMeshDimension() const
3175 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3180 * Returns a length of the nodal connectivity array.
3181 * This method is for test reason. Normally the integer returned is not useable by
3182 * user. For more info see \ref MEDCouplingUMeshNodalConnectivity.
3183 * \return int - the length of the nodal connectivity array.
3185 int MEDCouplingUMesh::getMeshLength() const
3187 return _nodal_connec->getNbOfElems();
3191 * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3193 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3195 MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3196 tinyInfo.push_back(getMeshDimension());
3197 tinyInfo.push_back(getNumberOfCells());
3199 tinyInfo.push_back(getMeshLength());
3201 tinyInfo.push_back(-1);
3205 * First step of unserialization process.
3207 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3209 return tinyInfo[6]<=0;
3213 * Second step of serialization process.
3214 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3216 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3218 MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3220 a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3224 * Third and final step of serialization process.
3226 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3228 MEDCouplingPointSet::serialize(a1,a2);
3229 if(getMeshDimension()>-1)
3231 a1=DataArrayInt::New();
3232 a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3233 int *ptA1=a1->getPointer();
3234 const int *conn=getNodalConnectivity()->getConstPointer();
3235 const int *index=getNodalConnectivityIndex()->getConstPointer();
3236 ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3237 std::copy(conn,conn+getMeshLength(),ptA1);
3244 * Second and final unserialization process.
3245 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3247 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3249 MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3250 setMeshDimension(tinyInfo[5]);
3254 const int *recvBuffer=a1->getConstPointer();
3255 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3256 myConnecIndex->alloc(tinyInfo[6]+1,1);
3257 std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3258 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3259 myConnec->alloc(tinyInfo[7],1);
3260 std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3261 setConnectivity(myConnec, myConnecIndex);
3266 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3267 * CellIds are given using range specified by a start an end and step.
3269 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3271 checkFullyDefined();
3272 int ncell=getNumberOfCells();
3273 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3274 ret->_mesh_dim=_mesh_dim;
3275 ret->setCoords(_coords);
3276 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3277 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3278 int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3280 const int *conn=_nodal_connec->getConstPointer();
3281 const int *connIndex=_nodal_connec_index->getConstPointer();
3282 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3284 if(work>=0 && work<ncell)
3286 newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3290 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3291 throw INTERP_KERNEL::Exception(oss.str().c_str());
3294 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3295 int *newConnPtr=newConn->getPointer();
3296 std::set<INTERP_KERNEL::NormalizedCellType> types;
3298 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3300 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3301 newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3303 ret->setConnectivity(newConn,newConnI,false);
3305 ret->copyTinyInfoFrom(this);
3310 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3311 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3312 * The return newly allocated mesh will share the same coordinates as \a this.
3314 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3316 checkConnectivityFullyDefined();
3317 int ncell=getNumberOfCells();
3318 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3319 ret->_mesh_dim=_mesh_dim;
3320 ret->setCoords(_coords);
3321 std::size_t nbOfElemsRet=std::distance(begin,end);
3322 int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3324 const int *conn=_nodal_connec->getConstPointer();
3325 const int *connIndex=_nodal_connec_index->getConstPointer();
3327 for(const int *work=begin;work!=end;work++,newNbring++)
3329 if(*work>=0 && *work<ncell)
3330 connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3334 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3335 throw INTERP_KERNEL::Exception(oss.str().c_str());
3338 int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3339 int *connRetWork=connRet;
3340 std::set<INTERP_KERNEL::NormalizedCellType> types;
3341 for(const int *work=begin;work!=end;work++)
3343 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3344 connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3346 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3347 connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3348 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3349 connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3350 ret->setConnectivity(connRetArr,connIndexRetArr,false);
3352 ret->copyTinyInfoFrom(this);
3357 * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3359 * For 1D cells, the returned field contains lengths.<br>
3360 * For 2D cells, the returned field contains areas.<br>
3361 * For 3D cells, the returned field contains volumes.
3362 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3363 * orientation, i.e. the volume is always positive.
3364 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3365 * and one time . The caller is to delete this field using decrRef() as it is no
3368 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3370 std::string name="MeasureOfMesh_";
3372 int nbelem=getNumberOfCells();
3373 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3374 field->setName(name);
3375 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3376 array->alloc(nbelem,1);
3377 double *area_vol=array->getPointer();
3378 field->setArray(array) ; array=0;
3379 field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3380 field->synchronizeTimeWithMesh();
3381 if(getMeshDimension()!=-1)
3384 INTERP_KERNEL::NormalizedCellType type;
3385 int dim_space=getSpaceDimension();
3386 const double *coords=getCoords()->getConstPointer();
3387 const int *connec=getNodalConnectivity()->getConstPointer();
3388 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3389 for(int iel=0;iel<nbelem;iel++)
3391 ipt=connec_index[iel];
3392 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3393 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);
3396 std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3400 area_vol[0]=std::numeric_limits<double>::max();
3402 return field.retn();
3406 * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3408 * For 1D cells, the returned array contains lengths.<br>
3409 * For 2D cells, the returned array contains areas.<br>
3410 * For 3D cells, the returned array contains volumes.
3411 * This method avoids building explicitly a part of \a this mesh to perform the work.
3412 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3413 * orientation, i.e. the volume is always positive.
3414 * \param [in] begin - an array of cell ids of interest.
3415 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3416 * \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3417 * delete this array using decrRef() as it is no more needed.
3419 * \if ENABLE_EXAMPLES
3420 * \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3421 * \ref py_mcumesh_getPartMeasureField "Here is a Python example".
3423 * \sa getMeasureField()
3425 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3427 std::string name="PartMeasureOfMesh_";
3429 int nbelem=(int)std::distance(begin,end);
3430 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3431 array->setName(name);
3432 array->alloc(nbelem,1);
3433 double *area_vol=array->getPointer();
3434 if(getMeshDimension()!=-1)
3437 INTERP_KERNEL::NormalizedCellType type;
3438 int dim_space=getSpaceDimension();
3439 const double *coords=getCoords()->getConstPointer();
3440 const int *connec=getNodalConnectivity()->getConstPointer();
3441 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3442 for(const int *iel=begin;iel!=end;iel++)
3444 ipt=connec_index[*iel];
3445 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3446 *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3449 std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3453 area_vol[0]=std::numeric_limits<double>::max();
3455 return array.retn();
3459 * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3460 * \a this one. The returned field contains the dual cell volume for each corresponding
3461 * node in \a this mesh. In other words, the field returns the getMeasureField() of
3462 * the dual mesh in P1 sens of \a this.<br>
3463 * For 1D cells, the returned field contains lengths.<br>
3464 * For 2D cells, the returned field contains areas.<br>
3465 * For 3D cells, the returned field contains volumes.
3466 * This method is useful to check "P1*" conservative interpolators.
3467 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3468 * orientation, i.e. the volume is always positive.
3469 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3470 * nodes and one time. The caller is to delete this array using decrRef() as
3471 * it is no more needed.
3473 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3475 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3476 std::string name="MeasureOnNodeOfMesh_";
3478 int nbNodes=getNumberOfNodes();
3479 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3480 double cst=1./((double)getMeshDimension()+1.);
3481 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3482 array->alloc(nbNodes,1);
3483 double *valsToFill=array->getPointer();
3484 std::fill(valsToFill,valsToFill+nbNodes,0.);
3485 const double *values=tmp->getArray()->getConstPointer();
3486 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3487 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3488 getReverseNodalConnectivity(da,daInd);
3489 const int *daPtr=da->getConstPointer();
3490 const int *daIPtr=daInd->getConstPointer();
3491 for(int i=0;i<nbNodes;i++)
3492 for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3493 valsToFill[i]+=cst*values[*cell];
3495 ret->setArray(array);
3500 * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3501 * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3502 * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3503 * and are normalized.
3504 * <br> \a this can be either
3505 * - a 2D mesh in 2D or 3D space or
3506 * - an 1D mesh in 2D space.
3508 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3509 * cells and one time. The caller is to delete this field using decrRef() as
3510 * it is no more needed.
3511 * \throw If the nodal connectivity of cells is not defined.
3512 * \throw If the coordinates array is not set.
3513 * \throw If the mesh dimension is not set.
3514 * \throw If the mesh and space dimension is not as specified above.
3516 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3518 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3519 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3520 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3521 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3522 int nbOfCells=getNumberOfCells();
3523 int nbComp=getMeshDimension()+1;
3524 array->alloc(nbOfCells,nbComp);
3525 double *vals=array->getPointer();
3526 const int *connI=_nodal_connec_index->getConstPointer();
3527 const int *conn=_nodal_connec->getConstPointer();
3528 const double *coords=_coords->getConstPointer();
3529 if(getMeshDimension()==2)
3531 if(getSpaceDimension()==3)
3533 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3534 const double *locPtr=loc->getConstPointer();
3535 for(int i=0;i<nbOfCells;i++,vals+=3)
3537 int offset=connI[i];
3538 INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3539 double n=INTERP_KERNEL::norm<3>(vals);
3540 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3545 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3546 const double *isAbsPtr=isAbs->getArray()->begin();
3547 for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3548 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3551 else//meshdimension==1
3554 for(int i=0;i<nbOfCells;i++)
3556 int offset=connI[i];
3557 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3558 double n=INTERP_KERNEL::norm<2>(tmp);
3559 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3564 ret->setArray(array);
3566 ret->synchronizeTimeWithSupport();
3571 * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3572 * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3573 * and are normalized.
3574 * <br> \a this can be either
3575 * - a 2D mesh in 2D or 3D space or
3576 * - an 1D mesh in 2D space.
3578 * This method avoids building explicitly a part of \a this mesh to perform the work.
3579 * \param [in] begin - an array of cell ids of interest.
3580 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3581 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3582 * cells and one time. The caller is to delete this field using decrRef() as
3583 * it is no more needed.
3584 * \throw If the nodal connectivity of cells is not defined.
3585 * \throw If the coordinates array is not set.
3586 * \throw If the mesh dimension is not set.
3587 * \throw If the mesh and space dimension is not as specified above.
3588 * \sa buildOrthogonalField()
3590 * \if ENABLE_EXAMPLES
3591 * \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3592 * \ref py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3595 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3597 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3598 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3599 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3600 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3601 std::size_t nbelems=std::distance(begin,end);
3602 int nbComp=getMeshDimension()+1;
3603 array->alloc((int)nbelems,nbComp);
3604 double *vals=array->getPointer();
3605 const int *connI=_nodal_connec_index->getConstPointer();
3606 const int *conn=_nodal_connec->getConstPointer();
3607 const double *coords=_coords->getConstPointer();
3608 if(getMeshDimension()==2)
3610 if(getSpaceDimension()==3)
3612 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3613 const double *locPtr=loc->getConstPointer();
3614 for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3616 int offset=connI[*i];
3617 INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3618 double n=INTERP_KERNEL::norm<3>(vals);
3619 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3624 for(std::size_t i=0;i<nbelems;i++)
3625 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3628 else//meshdimension==1
3631 for(const int *i=begin;i!=end;i++)
3633 int offset=connI[*i];
3634 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3635 double n=INTERP_KERNEL::norm<2>(tmp);
3636 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3641 ret->setArray(array);
3643 ret->synchronizeTimeWithSupport();
3648 * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3649 * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3650 * and are \b not normalized.
3651 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3652 * cells and one time. The caller is to delete this field using decrRef() as
3653 * it is no more needed.
3654 * \throw If the nodal connectivity of cells is not defined.
3655 * \throw If the coordinates array is not set.
3656 * \throw If \a this->getMeshDimension() != 1.
3657 * \throw If \a this mesh includes cells of type other than SEG2.
3659 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3661 if(getMeshDimension()!=1)
3662 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3663 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3664 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3665 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3666 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3667 int nbOfCells=getNumberOfCells();
3668 int spaceDim=getSpaceDimension();
3669 array->alloc(nbOfCells,spaceDim);
3670 double *pt=array->getPointer();
3671 const double *coo=getCoords()->getConstPointer();
3672 std::vector<int> conn;
3674 for(int i=0;i<nbOfCells;i++)
3677 getNodeIdsOfCell(i,conn);
3678 pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3680 ret->setArray(array);
3682 ret->synchronizeTimeWithSupport();
3687 * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3688 * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3689 * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3690 * from. If a result face is shared by two 3D cells, then the face in included twice in
3692 * \param [in] origin - 3 components of a point defining location of the plane.
3693 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3694 * must be greater than 1e-6.
3695 * \param [in] eps - half-thickness of the plane.
3696 * \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3697 * producing correspondent 2D cells. The caller is to delete this array
3698 * using decrRef() as it is no more needed.
3699 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3700 * not share the node coordinates array with \a this mesh. The caller is to
3701 * delete this mesh using decrRef() as it is no more needed.
3702 * \throw If the coordinates array is not set.
3703 * \throw If the nodal connectivity of cells is not defined.
3704 * \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3705 * \throw If magnitude of \a vec is less than 1e-6.
3706 * \throw If the plane does not intersect any 3D cell of \a this mesh.
3707 * \throw If \a this includes quadratic cells.
3709 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3711 checkFullyDefined();
3712 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3713 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3714 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3715 if(candidates->empty())
3716 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3717 std::vector<int> nodes;
3718 DataArrayInt *cellIds1D=0;
3719 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3720 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3721 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3722 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3723 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3724 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3725 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3726 revDesc2=0; revDescIndx2=0;
3727 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3728 revDesc1=0; revDescIndx1=0;
3729 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3730 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3732 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3733 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3735 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3736 std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3737 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3738 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3739 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3740 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3741 connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3742 subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3743 if(cellIds2->empty())
3744 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3745 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3746 ret->setCoords(mDesc1->getCoords());
3747 ret->setConnectivity(conn,connI,true);
3748 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3753 * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3754 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
3755 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3757 * \param [in] origin - 3 components of a point defining location of the plane.
3758 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3759 * must be greater than 1e-6.
3760 * \param [in] eps - half-thickness of the plane.
3761 * \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3762 * producing correspondent segments. The caller is to delete this array
3763 * using decrRef() as it is no more needed.
3764 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3765 * mesh in 3D space. This mesh does not share the node coordinates array with
3766 * \a this mesh. The caller is to delete this mesh using decrRef() as it is
3768 * \throw If the coordinates array is not set.
3769 * \throw If the nodal connectivity of cells is not defined.
3770 * \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3771 * \throw If magnitude of \a vec is less than 1e-6.
3772 * \throw If the plane does not intersect any 2D cell of \a this mesh.
3773 * \throw If \a this includes quadratic cells.
3775 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3777 checkFullyDefined();
3778 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3779 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3780 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3781 if(candidates->empty())
3782 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3783 std::vector<int> nodes;
3784 DataArrayInt *cellIds1D=0;
3785 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3786 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3787 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3788 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3789 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3790 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3791 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3792 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3793 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3795 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3796 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3798 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3799 int ncellsSub=subMesh->getNumberOfCells();
3800 std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3801 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3802 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3803 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3804 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3806 const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3807 const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3808 for(int i=0;i<ncellsSub;i++)
3810 if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3812 if(cut3DSurf[i].first!=-2)
3814 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3815 connI->pushBackSilent(conn->getNumberOfTuples());
3816 cellIds2->pushBackSilent(i);
3820 int cellId3DSurf=cut3DSurf[i].second;
3821 int offset=nodalI[cellId3DSurf]+1;
3822 int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3823 for(int j=0;j<nbOfEdges;j++)
3825 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3826 connI->pushBackSilent(conn->getNumberOfTuples());
3827 cellIds2->pushBackSilent(cellId3DSurf);
3832 if(cellIds2->empty())
3833 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3834 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3835 ret->setCoords(mDesc1->getCoords());
3836 ret->setConnectivity(conn,connI,true);
3837 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3842 * Finds cells whose bounding boxes intersect a given plane.
3843 * \param [in] origin - 3 components of a point defining location of the plane.
3844 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3845 * must be greater than 1e-6.
3846 * \param [in] eps - half-thickness of the plane.
3847 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3848 * cells. The caller is to delete this array using decrRef() as it is no more
3850 * \throw If the coordinates array is not set.
3851 * \throw If the nodal connectivity of cells is not defined.
3852 * \throw If \a this->getSpaceDimension() != 3.
3853 * \throw If magnitude of \a vec is less than 1e-6.
3854 * \sa buildSlice3D()
3856 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3858 checkFullyDefined();
3859 if(getSpaceDimension()!=3)
3860 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3861 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3863 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3865 vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3866 double angle=acos(vec[2]/normm);
3867 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3871 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3872 MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3873 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3875 mw->getBoundingBox(bbox);
3876 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3877 cellIds=mw->getCellsInBoundingBox(bbox,eps);
3881 getBoundingBox(bbox);
3882 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3883 cellIds=getCellsInBoundingBox(bbox,eps);
3885 return cellIds.retn();
3889 * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3890 * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3891 * No consideration of coordinate is done by this method.
3892 * 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)
3893 * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3895 bool MEDCouplingUMesh::isContiguous1D() const
3897 if(getMeshDimension()!=1)
3898 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3899 int nbCells=getNumberOfCells();
3901 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3902 const int *connI=_nodal_connec_index->getConstPointer();
3903 const int *conn=_nodal_connec->getConstPointer();
3904 int ref=conn[connI[0]+2];
3905 for(int i=1;i<nbCells;i++)
3907 if(conn[connI[i]+1]!=ref)
3909 ref=conn[connI[i]+2];
3915 * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3916 * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3917 * \param pt reference point of the line
3918 * \param v normalized director vector of the line
3919 * \param eps max precision before throwing an exception
3920 * \param res output of size this->getNumberOfCells
3922 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3924 if(getMeshDimension()!=1)
3925 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3926 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3927 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3928 if(getSpaceDimension()!=3)
3929 throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3930 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3931 const double *fPtr=f->getArray()->getConstPointer();
3933 for(int i=0;i<getNumberOfCells();i++)
3935 const double *tmp1=fPtr+3*i;
3936 tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3937 tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3938 tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3939 double n1=INTERP_KERNEL::norm<3>(tmp);
3940 n1/=INTERP_KERNEL::norm<3>(tmp1);
3942 throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3944 const double *coo=getCoords()->getConstPointer();
3945 for(int i=0;i<getNumberOfNodes();i++)
3947 std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3948 std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3949 res[i]=std::accumulate(tmp,tmp+3,0.);
3954 * 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.
3955 * \a this is expected to be a mesh so that its space dimension is equal to its
3956 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3957 * 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).
3959 * 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
3960 * 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).
3961 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3963 * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3964 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3966 * \param [in] ptBg the start pointer (included) of the coordinates of the point
3967 * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3968 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3969 * \return the positive value of the distance.
3970 * \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
3972 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3974 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
3976 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3977 if(meshDim!=spaceDim-1)
3978 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3979 if(meshDim!=2 && meshDim!=1)
3980 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3981 checkFullyDefined();
3982 if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3983 { 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()); }
3984 DataArrayInt *ret1=0;
3985 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
3986 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
3987 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
3988 cellId=*ret1Safe->begin();
3989 return *ret0->begin();
3993 * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
3994 * to \a this and the first \a cellId in \a this corresponding to the returned distance.
3995 * 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
3996 * 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).
3997 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3999 * \a this is expected to be a mesh so that its space dimension is equal to its
4000 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4001 * 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).
4003 * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
4004 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4006 * \param [in] pts the list of points in which each tuple represents a point
4007 * \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.
4008 * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
4009 * \throw if number of components of \a pts is not equal to the space dimension.
4010 * \throw if mesh dimension of \a this is not equal to space dimension - 1.
4011 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
4013 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
4016 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
4017 pts->checkAllocated();
4018 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4019 if(meshDim!=spaceDim-1)
4020 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
4021 if(meshDim!=2 && meshDim!=1)
4022 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
4023 if(pts->getNumberOfComponents()!=spaceDim)
4025 std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
4026 throw INTERP_KERNEL::Exception(oss.str().c_str());
4028 checkFullyDefined();
4029 int nbCells=getNumberOfCells();
4031 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4032 int nbOfPts=pts->getNumberOfTuples();
4033 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4034 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4035 const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4036 double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4037 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4038 const double *bbox(bboxArr->begin());
4043 BBTreeDst<3> myTree(bbox,0,0,nbCells);
4044 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4046 double x=std::numeric_limits<double>::max();
4047 std::vector<int> elems;
4048 myTree.getMinDistanceOfMax(ptsPtr,x);
4049 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4050 DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4056 BBTreeDst<2> myTree(bbox,0,0,nbCells);
4057 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4059 double x=std::numeric_limits<double>::max();
4060 std::vector<int> elems;
4061 myTree.getMinDistanceOfMax(ptsPtr,x);
4062 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4063 DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4068 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4070 cellIds=ret1.retn();
4075 * \param [in] pt the start pointer (included) of the coordinates of the point
4076 * \param [in] cellIdsBg the start pointer (included) of cellIds
4077 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4078 * \param [in] nc nodal connectivity
4079 * \param [in] ncI nodal connectivity index
4080 * \param [in,out] ret0 the min distance between \a this and the external input point
4081 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4082 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4084 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)
4087 ret0=std::numeric_limits<double>::max();
4088 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4090 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4092 case INTERP_KERNEL::NORM_TRI3:
4094 double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4096 { ret0=tmp; cellId=*zeCell; }
4099 case INTERP_KERNEL::NORM_QUAD4:
4100 case INTERP_KERNEL::NORM_POLYGON:
4102 double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4104 { ret0=tmp; cellId=*zeCell; }
4108 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4114 * \param [in] pt the start pointer (included) of the coordinates of the point
4115 * \param [in] cellIdsBg the start pointer (included) of cellIds
4116 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4117 * \param [in] nc nodal connectivity
4118 * \param [in] ncI nodal connectivity index
4119 * \param [in,out] ret0 the min distance between \a this and the external input point
4120 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4121 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4123 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)
4126 ret0=std::numeric_limits<double>::max();
4127 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4129 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4131 case INTERP_KERNEL::NORM_SEG2:
4133 std::size_t uselessEntry=0;
4134 double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4137 { ret0=tmp; cellId=*zeCell; }
4141 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4147 * Finds cells in contact with a ball (i.e. a point with precision).
4148 * 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.
4149 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4151 * \warning This method is suitable if the caller intends to evaluate only one
4152 * point, for more points getCellsContainingPoints() is recommended as it is
4154 * \param [in] pos - array of coordinates of the ball central point.
4155 * \param [in] eps - ball radius.
4156 * \return int - a smallest id of cells being in contact with the ball, -1 in case
4157 * if there are no such cells.
4158 * \throw If the coordinates array is not set.
4159 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4161 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4163 std::vector<int> elts;
4164 getCellsContainingPoint(pos,eps,elts);
4167 return elts.front();
4171 * Finds cells in contact with a ball (i.e. a point with precision).
4172 * 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.
4173 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4174 * \warning This method is suitable if the caller intends to evaluate only one
4175 * point, for more points getCellsContainingPoints() is recommended as it is
4177 * \param [in] pos - array of coordinates of the ball central point.
4178 * \param [in] eps - ball radius.
4179 * \param [out] elts - vector returning ids of the found cells. It is cleared
4180 * before inserting ids.
4181 * \throw If the coordinates array is not set.
4182 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4184 * \if ENABLE_EXAMPLES
4185 * \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4186 * \ref py_mcumesh_getCellsContainingPoint "Here is a Python example".
4189 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4191 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4192 getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4193 elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4198 namespace ParaMEDMEM
4200 template<const int SPACEDIMM>
4204 static const int MY_SPACEDIM=SPACEDIMM;
4205 static const int MY_MESHDIM=8;
4206 typedef int MyConnType;
4207 static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4209 // useless, but for windows compilation ...
4210 const double* getCoordinatesPtr() const { return 0; }
4211 const int* getConnectivityPtr() const { return 0; }
4212 const int* getConnectivityIndexPtr() const { return 0; }
4213 INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4220 * Warning the nodes in \a m should be decrRefed ! To avoid that Node * pointer be replaced by another instance.
4222 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m)
4224 INTERP_KERNEL::Edge *ret(0);
4225 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]));
4226 m[n0]=bg[0]; m[n1]=bg[1];
4229 case INTERP_KERNEL::NORM_SEG2:
4231 ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4234 case INTERP_KERNEL::NORM_SEG3:
4236 INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4237 INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4238 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4239 // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4240 bool colinearity(inters.areColinears());
4241 delete e1; delete e2;
4243 { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4245 { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4249 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4254 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4256 INTERP_KERNEL::Edge *ret=0;
4259 case INTERP_KERNEL::NORM_SEG2:
4261 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4264 case INTERP_KERNEL::NORM_SEG3:
4266 INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4267 INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4268 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4269 // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4270 bool colinearity=inters.areColinears();
4271 delete e1; delete e2;
4273 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4275 ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4276 mapp2[bg[2]].second=false;
4280 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4286 * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4287 * the global mesh 'mDesc'.
4288 * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4289 * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4291 INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4292 std::map<INTERP_KERNEL::Node *,int>& mapp)
4295 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.
4296 const double *coo=mDesc->getCoords()->getConstPointer();
4297 const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4298 const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4300 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4301 s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4302 for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4304 INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4305 mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4307 INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4308 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4310 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4311 ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4313 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4315 if((*it2).second.second)
4316 mapp[(*it2).second.first]=(*it2).first;
4317 ((*it2).second.first)->decrRef();
4322 INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4326 int locId=nodeId-offset2;
4327 return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4331 int locId=nodeId-offset1;
4332 return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4334 return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4338 * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4340 void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4341 const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4342 /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4344 for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4346 int eltId1=abs(*desc1)-1;
4347 for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4349 std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4350 if(it==mappRev.end())
4352 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4363 template<int SPACEDIM>
4364 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4365 double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4367 elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4368 int *eltsIndexPtr(eltsIndex->getPointer());
4369 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4370 const double *bbox(bboxArr->begin());
4371 int nbOfCells=getNumberOfCells();
4372 const int *conn=_nodal_connec->getConstPointer();
4373 const int *connI=_nodal_connec_index->getConstPointer();
4374 double bb[2*SPACEDIM];
4375 BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4376 for(int i=0;i<nbOfPoints;i++)
4378 eltsIndexPtr[i+1]=eltsIndexPtr[i];
4379 for(int j=0;j<SPACEDIM;j++)
4381 bb[2*j]=pos[SPACEDIM*i+j];
4382 bb[2*j+1]=pos[SPACEDIM*i+j];
4384 std::vector<int> candidates;
4385 myTree.getIntersectingElems(bb,candidates);
4386 for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4388 int sz(connI[(*iter)+1]-connI[*iter]-1);
4389 INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4391 if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4392 status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4396 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4397 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4398 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4399 std::vector<INTERP_KERNEL::Node *> nodes(sz);
4400 INTERP_KERNEL::QuadraticPolygon *pol(0);
4401 for(int j=0;j<sz;j++)
4403 int nodeId(conn[connI[*iter]+1+j]);
4404 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4406 if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4407 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4409 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4410 INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4411 double a(0.),b(0.),c(0.);
4412 a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4413 status=pol->isInOrOut2(n);
4414 delete pol; n->decrRef();
4418 eltsIndexPtr[i+1]++;
4419 elts->pushBackSilent(*iter);
4425 * Finds cells in contact with several balls (i.e. points with precision).
4426 * This method is an extension of getCellContainingPoint() and
4427 * getCellsContainingPoint() for the case of multiple points.
4428 * 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.
4429 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4430 * \param [in] pos - an array of coordinates of points in full interlace mode :
4431 * X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4432 * this->getSpaceDimension() * \a nbOfPoints
4433 * \param [in] nbOfPoints - number of points to locate within \a this mesh.
4434 * \param [in] eps - radius of balls (i.e. the precision).
4435 * \param [out] elts - vector returning ids of found cells.
4436 * \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4437 * dividing cell ids in \a elts into groups each referring to one
4438 * point. Its every element (except the last one) is an index pointing to the
4439 * first id of a group of cells. For example cells in contact with the *i*-th
4440 * point are described by following range of indices:
4441 * [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4442 * \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4443 * Number of cells in contact with the *i*-th point is
4444 * \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4445 * \throw If the coordinates array is not set.
4446 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4448 * \if ENABLE_EXAMPLES
4449 * \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4450 * \ref py_mcumesh_getCellsContainingPoints "Here is a Python example".
4453 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4454 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4456 int spaceDim=getSpaceDimension();
4457 int mDim=getMeshDimension();
4462 const double *coords=_coords->getConstPointer();
4463 getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4470 throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4472 else if(spaceDim==2)
4476 const double *coords=_coords->getConstPointer();
4477 getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4480 throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4482 else if(spaceDim==1)
4486 const double *coords=_coords->getConstPointer();
4487 getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4490 throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4493 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4497 * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4498 * least two its edges intersect each other anywhere except their extremities. An
4499 * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4500 * \param [in,out] cells - a vector returning ids of the found cells. It is not
4501 * cleared before filling in.
4502 * \param [in] eps - precision.
4503 * \throw If \a this->getMeshDimension() != 2.
4504 * \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4506 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4508 const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4509 if(getMeshDimension()!=2)
4510 throw INTERP_KERNEL::Exception(msg);
4511 int spaceDim=getSpaceDimension();
4512 if(spaceDim!=2 && spaceDim!=3)
4513 throw INTERP_KERNEL::Exception(msg);
4514 const int *conn=_nodal_connec->getConstPointer();
4515 const int *connI=_nodal_connec_index->getConstPointer();
4516 int nbOfCells=getNumberOfCells();
4517 std::vector<double> cell2DinS2;
4518 for(int i=0;i<nbOfCells;i++)
4520 int offset=connI[i];
4521 int nbOfNodesForCell=connI[i+1]-offset-1;
4522 if(nbOfNodesForCell<=3)
4524 bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4525 project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4526 if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4533 * This method is typically requested to unbutterfly 2D linear cells in \b this.
4535 * 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.
4536 * 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.
4538 * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4539 * This convex envelop is computed using Jarvis march algorithm.
4540 * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4541 * 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)
4542 * 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.
4544 * \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.
4545 * \sa MEDCouplingUMesh::colinearize2D
4547 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4549 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4550 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D works only for meshDim=2 and spaceDim=2 !");
4551 checkFullyDefined();
4552 const double *coords=getCoords()->getConstPointer();
4553 int nbOfCells=getNumberOfCells();
4554 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4555 nodalConnecIndexOut->alloc(nbOfCells+1,1);
4556 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4557 int *workIndexOut=nodalConnecIndexOut->getPointer();
4559 const int *nodalConnecIn=_nodal_connec->getConstPointer();
4560 const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4561 std::set<INTERP_KERNEL::NormalizedCellType> types;
4562 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4563 isChanged->alloc(0,1);
4564 for(int i=0;i<nbOfCells;i++,workIndexOut++)
4566 int pos=nodalConnecOut->getNumberOfTuples();
4567 if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4568 isChanged->pushBackSilent(i);
4569 types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4570 workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4572 if(isChanged->empty())
4574 setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4576 return isChanged.retn();
4580 * This method is \b NOT const because it can modify \a this.
4581 * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4582 * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4583 * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4584 * \b 1 for translation and rotation around point of 'mesh1D'.
4585 * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.
4587 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4589 checkFullyDefined();
4590 mesh1D->checkFullyDefined();
4591 if(!mesh1D->isContiguous1D())
4592 throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4593 if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4594 throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4595 if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4596 throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4597 if(mesh1D->getMeshDimension()!=1)
4598 throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4600 if(isPresenceOfQuadratic())
4602 if(mesh1D->isFullyQuadratic())
4605 throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4608 int oldNbOfNodes=getNumberOfNodes();
4609 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4614 newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4619 newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4623 throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4625 setCoords(newCoords);
4626 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4632 * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4633 * If it is not the case an exception will be thrown.
4634 * This method is non const because the coordinate of \a this can be appended with some new points issued from
4635 * intersection of plane defined by ('origin','vec').
4636 * This method has one in/out parameter : 'cut3DCurve'.
4637 * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4638 * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4639 * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4640 * This method will throw an exception if \a this contains a non linear segment.
4642 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4644 checkFullyDefined();
4645 if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4646 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4647 int ncells=getNumberOfCells();
4648 int nnodes=getNumberOfNodes();
4649 double vec2[3],vec3[3],vec4[3];
4650 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4652 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4653 vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4654 const int *conn=_nodal_connec->getConstPointer();
4655 const int *connI=_nodal_connec_index->getConstPointer();
4656 const double *coo=_coords->getConstPointer();
4657 std::vector<double> addCoo;
4658 for(int i=0;i<ncells;i++)
4660 if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4662 if(cut3DCurve[i]==-2)
4664 int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4665 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];
4666 double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4667 double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4668 if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4670 const double *st2=coo+3*st;
4671 vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4672 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]));
4673 if(pos>eps && pos<1-eps)
4675 int nNode=((int)addCoo.size())/3;
4676 vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4677 addCoo.insert(addCoo.end(),vec4,vec4+3);
4678 cut3DCurve[i]=nnodes+nNode;
4684 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4688 int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4689 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4690 coo2->alloc(newNbOfNodes,3);
4691 double *tmp=coo2->getPointer();
4692 tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4693 std::copy(addCoo.begin(),addCoo.end(),tmp);
4694 DataArrayDouble::SetArrayIn(coo2,_coords);
4699 * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4700 * \param mesh1D is the input 1D mesh used for translation computation.
4701 * \return newCoords new coords filled by this method.
4703 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4705 int oldNbOfNodes=getNumberOfNodes();
4706 int nbOf1DCells=mesh1D->getNumberOfCells();
4707 int spaceDim=getSpaceDimension();
4708 DataArrayDouble *ret=DataArrayDouble::New();
4709 std::vector<bool> isQuads;
4710 int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4711 ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4712 double *retPtr=ret->getPointer();
4713 const double *coords=getCoords()->getConstPointer();
4714 double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4716 std::vector<double> c;
4720 for(int i=0;i<nbOf1DCells;i++)
4723 mesh1D->getNodeIdsOfCell(i,v);
4725 mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4726 mesh1D->getCoordinatesOfNode(v[0],c);
4727 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4728 for(int j=0;j<oldNbOfNodes;j++)
4729 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4733 mesh1D->getCoordinatesOfNode(v[1],c);
4734 mesh1D->getCoordinatesOfNode(v[0],c);
4735 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4736 for(int j=0;j<oldNbOfNodes;j++)
4737 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4740 ret->copyStringInfoFrom(*getCoords());
4745 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4746 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4747 * \return newCoords new coords filled by this method.
4749 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4751 if(mesh1D->getSpaceDimension()==2)
4752 return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4753 if(mesh1D->getSpaceDimension()==3)
4754 return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4755 throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4759 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4760 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4761 * \return newCoords new coords filled by this method.
4763 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4766 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4767 int oldNbOfNodes=getNumberOfNodes();
4768 int nbOf1DCells=mesh1D->getNumberOfCells();
4770 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4771 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4772 int nbOfLevsInVec=nbOf1DCells+1;
4773 ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4774 double *retPtr=ret->getPointer();
4775 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4776 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4777 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4778 tmp->setCoords(tmp2);
4779 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4780 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4781 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4782 for(int i=1;i<nbOfLevsInVec;i++)
4784 const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4785 const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4786 const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4787 const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4788 tmp->translate(vec);
4789 double tmp3[2],radius,alpha,alpha0;
4790 const double *p0=i+1<nbOfLevsInVec?begin:third;
4791 const double *p1=i+1<nbOfLevsInVec?end:begin;
4792 const double *p2=i+1<nbOfLevsInVec?third:end;
4793 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4794 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]);
4795 double angle=acos(cosangle/(radius*radius));
4796 tmp->rotate(end,0,angle);
4797 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4803 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4804 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4805 * \return newCoords new coords filled by this method.
4807 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4810 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4811 int oldNbOfNodes=getNumberOfNodes();
4812 int nbOf1DCells=mesh1D->getNumberOfCells();
4814 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4815 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4816 int nbOfLevsInVec=nbOf1DCells+1;
4817 ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4818 double *retPtr=ret->getPointer();
4819 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4820 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4821 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4822 tmp->setCoords(tmp2);
4823 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4824 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4825 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4826 for(int i=1;i<nbOfLevsInVec;i++)
4828 const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4829 const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4830 const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4831 const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4832 tmp->translate(vec);
4833 double tmp3[2],radius,alpha,alpha0;
4834 const double *p0=i+1<nbOfLevsInVec?begin:third;
4835 const double *p1=i+1<nbOfLevsInVec?end:begin;
4836 const double *p2=i+1<nbOfLevsInVec?third:end;
4837 double vecPlane[3]={
4838 (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4839 (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4840 (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4842 double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4845 vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4846 double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4847 double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4849 double c2=cos(asin(s2));
4851 {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4852 {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4853 {-vec2[1]*s2, vec2[0]*s2, c2}
4855 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]};
4856 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]};
4857 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]};
4858 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4859 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]);
4860 double angle=acos(cosangle/(radius*radius));
4861 tmp->rotate(end,vecPlane,angle);
4863 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4869 * This method is private because not easy to use for end user. This method is const contrary to
4870 * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4871 * the coords sorted slice by slice.
4872 * \param isQuad specifies presence of quadratic cells.
4874 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4876 int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4877 int nbOf2DCells=getNumberOfCells();
4878 int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4879 MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4880 const int *conn=_nodal_connec->getConstPointer();
4881 const int *connI=_nodal_connec_index->getConstPointer();
4882 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4883 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4884 newConnI->alloc(nbOf3DCells+1,1);
4885 int *newConnIPtr=newConnI->getPointer();
4887 std::vector<int> newc;
4888 for(int j=0;j<nbOf2DCells;j++)
4890 AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4891 *newConnIPtr++=(int)newc.size();
4893 newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4894 int *newConnPtr=newConn->getPointer();
4895 int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4896 newConnIPtr=newConnI->getPointer();
4897 for(int iz=0;iz<nbOf1DCells;iz++)
4900 std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4901 for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4903 int icell=(int)(iter-newc.begin());
4904 if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4907 *newConnPtr=(*iter)+iz*deltaPerLev;
4912 *newConnPtr=(*iter);
4915 ret->setConnectivity(newConn,newConnI,true);
4916 ret->setCoords(getCoords());
4921 * Checks if \a this mesh is constituted by only quadratic cells.
4922 * \return bool - \c true if there are only quadratic cells in \a this mesh.
4923 * \throw If the coordinates array is not set.
4924 * \throw If the nodal connectivity of cells is not defined.
4926 bool MEDCouplingUMesh::isFullyQuadratic() const
4928 checkFullyDefined();
4930 int nbOfCells=getNumberOfCells();
4931 for(int i=0;i<nbOfCells && ret;i++)
4933 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4934 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4935 ret=cm.isQuadratic();
4941 * Checks if \a this mesh includes any quadratic cell.
4942 * \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4943 * \throw If the coordinates array is not set.
4944 * \throw If the nodal connectivity of cells is not defined.
4946 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4948 checkFullyDefined();
4950 int nbOfCells=getNumberOfCells();
4951 for(int i=0;i<nbOfCells && !ret;i++)
4953 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4954 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4955 ret=cm.isQuadratic();
4961 * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4962 * this mesh, it remains unchanged.
4963 * \throw If the coordinates array is not set.
4964 * \throw If the nodal connectivity of cells is not defined.
4966 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4968 checkFullyDefined();
4969 int nbOfCells=getNumberOfCells();
4971 const int *iciptr=_nodal_connec_index->getConstPointer();
4972 for(int i=0;i<nbOfCells;i++)
4974 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4975 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4976 if(cm.isQuadratic())
4978 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4979 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4980 if(!cml.isDynamic())
4981 delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4983 delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4988 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4989 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4990 const int *icptr=_nodal_connec->getConstPointer();
4991 newConn->alloc(getMeshLength()-delta,1);
4992 newConnI->alloc(nbOfCells+1,1);
4993 int *ocptr=newConn->getPointer();
4994 int *ociptr=newConnI->getPointer();
4997 for(int i=0;i<nbOfCells;i++,ociptr++)
4999 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
5000 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5001 if(!cm.isQuadratic())
5003 _types.insert(type);
5004 ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5005 ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5009 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5010 _types.insert(typel);
5011 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5012 int newNbOfNodes=cml.getNumberOfNodes();
5014 newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
5015 *ocptr++=(int)typel;
5016 ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5017 ociptr[1]=ociptr[0]+newNbOfNodes+1;
5020 setConnectivity(newConn,newConnI,false);
5024 * This method converts all linear cell in \a this to quadratic one.
5025 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5026 * 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)
5027 * 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.
5028 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5029 * end of the existing coordinates.
5031 * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5032 * corresponding quadratic cells. 1 is those creating the 'most' complex.
5033 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5035 * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5037 * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5039 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5041 DataArrayInt *conn=0,*connI=0;
5042 DataArrayDouble *coords=0;
5043 std::set<INTERP_KERNEL::NormalizedCellType> types;
5044 checkFullyDefined();
5045 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5046 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5047 int meshDim=getMeshDimension();
5048 switch(conversionType)
5054 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5055 connSafe=conn; connISafe=connI; coordsSafe=coords;
5058 ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5059 connSafe=conn; connISafe=connI; coordsSafe=coords;
5062 ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5063 connSafe=conn; connISafe=connI; coordsSafe=coords;
5066 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5074 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5075 connSafe=conn; connISafe=connI; coordsSafe=coords;
5078 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5079 connSafe=conn; connISafe=connI; coordsSafe=coords;
5082 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5083 connSafe=conn; connISafe=connI; coordsSafe=coords;
5086 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5091 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5093 setConnectivity(connSafe,connISafe,false);
5095 setCoords(coordsSafe);
5101 * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
5102 * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
5103 * The nodes to be added in those 2D cells are defined by the pair of \a nodeIdsToAdd and \a nodeIdsIndexToAdd.
5104 * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
5105 * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
5106 * This method can be seen as the opposite method of colinearize2D.
5107 * 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
5108 * to avoid to modify the numbering of existing nodes.
5110 * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
5111 * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
5112 * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
5113 * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
5114 * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
5115 * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
5116 * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
5118 * \sa buildDescendingConnectivity2
5120 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
5121 const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
5123 if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
5124 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
5125 nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
5126 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
5127 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
5128 if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
5129 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
5130 //DataArrayInt *out0(0),*outi0(0);
5131 //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
5132 //MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s(out0),outi0s(outi0);
5133 //out0s=out0s->buildUnique(); out0s->sort(true);
5138 * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5139 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5140 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5142 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5144 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5145 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5146 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5147 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5148 int nbOfCells=getNumberOfCells();
5149 int nbOfNodes=getNumberOfNodes();
5150 const int *cPtr=_nodal_connec->getConstPointer();
5151 const int *icPtr=_nodal_connec_index->getConstPointer();
5152 int lastVal=0,offset=nbOfNodes;
5153 for(int i=0;i<nbOfCells;i++,icPtr++)
5155 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5156 if(type==INTERP_KERNEL::NORM_SEG2)
5158 types.insert(INTERP_KERNEL::NORM_SEG3);
5159 newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5160 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5161 newConn->pushBackSilent(offset++);
5163 newConnI->pushBackSilent(lastVal);
5164 ret->pushBackSilent(i);
5169 lastVal+=(icPtr[1]-icPtr[0]);
5170 newConnI->pushBackSilent(lastVal);
5171 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5174 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5175 coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5179 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
5181 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5182 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5183 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5185 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5186 DataArrayInt *conn1D=0,*conn1DI=0;
5187 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5188 DataArrayDouble *coordsTmp=0;
5189 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5190 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5191 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5192 const int *c1DPtr=conn1D->begin();
5193 const int *c1DIPtr=conn1DI->begin();
5194 int nbOfCells=getNumberOfCells();
5195 const int *cPtr=_nodal_connec->getConstPointer();
5196 const int *icPtr=_nodal_connec_index->getConstPointer();
5198 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5200 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5201 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5202 if(!cm.isQuadratic())
5204 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5205 types.insert(typ2); newConn->pushBackSilent(typ2);
5206 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5207 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5208 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5209 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5210 newConnI->pushBackSilent(lastVal);
5211 ret->pushBackSilent(i);
5216 lastVal+=(icPtr[1]-icPtr[0]);
5217 newConnI->pushBackSilent(lastVal);
5218 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5221 conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5226 * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5227 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5228 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5230 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5232 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5233 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5234 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5237 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5239 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5240 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5242 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5243 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5244 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5246 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5247 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5248 DataArrayInt *conn1D=0,*conn1DI=0;
5249 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5250 DataArrayDouble *coordsTmp=0;
5251 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5252 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5253 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5254 const int *c1DPtr=conn1D->begin();
5255 const int *c1DIPtr=conn1DI->begin();
5256 int nbOfCells=getNumberOfCells();
5257 const int *cPtr=_nodal_connec->getConstPointer();
5258 const int *icPtr=_nodal_connec_index->getConstPointer();
5259 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5260 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5262 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5263 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5264 if(!cm.isQuadratic())
5266 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5267 types.insert(typ2); newConn->pushBackSilent(typ2);
5268 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5269 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5270 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5271 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5272 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5273 newConnI->pushBackSilent(lastVal);
5274 ret->pushBackSilent(i);
5279 lastVal+=(icPtr[1]-icPtr[0]);
5280 newConnI->pushBackSilent(lastVal);
5281 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5284 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5285 coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5290 * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5291 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5292 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5294 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5296 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5297 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5298 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5301 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5303 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5304 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5305 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5306 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5308 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5309 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5310 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5312 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5313 const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5314 DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5315 std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5316 DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5317 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5318 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5319 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5320 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5321 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5322 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5323 const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5324 int nbOfCells=getNumberOfCells();
5325 const int *cPtr=_nodal_connec->getConstPointer();
5326 const int *icPtr=_nodal_connec_index->getConstPointer();
5327 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5328 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5330 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5331 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5332 if(!cm.isQuadratic())
5334 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5335 if(typ2==INTERP_KERNEL::NORM_ERROR)
5337 std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5338 throw INTERP_KERNEL::Exception(oss.str().c_str());
5340 types.insert(typ2); newConn->pushBackSilent(typ2);
5341 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5342 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5343 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5344 for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5346 int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5347 int tmpPos=newConn->getNumberOfTuples();
5348 newConn->pushBackSilent(nodeId2);
5349 ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5351 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5352 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5353 newConnI->pushBackSilent(lastVal);
5354 ret->pushBackSilent(i);
5359 lastVal+=(icPtr[1]-icPtr[0]);
5360 newConnI->pushBackSilent(lastVal);
5361 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5364 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5365 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5366 coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5367 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5368 std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5369 int *c=newConn->getPointer();
5370 const int *cI(newConnI->begin());
5371 for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5372 c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5373 offset=coordsTmp2Safe->getNumberOfTuples();
5374 for(const int *elt=ret->begin();elt!=ret->end();elt++)
5375 c[cI[(*elt)+1]-1]+=offset;
5376 coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5381 * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5382 * so that the number of cells remains the same. Quadratic faces are converted to
5383 * polygons. This method works only for 2D meshes in
5384 * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5385 * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5386 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5387 * \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5388 * a polylinized edge constituting the input polygon.
5389 * \throw If the coordinates array is not set.
5390 * \throw If the nodal connectivity of cells is not defined.
5391 * \throw If \a this->getMeshDimension() != 2.
5392 * \throw If \a this->getSpaceDimension() != 2.
5394 void MEDCouplingUMesh::tessellate2D(double eps)
5396 checkFullyDefined();
5397 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
5398 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5399 double epsa=fabs(eps);
5400 if(epsa<std::numeric_limits<double>::min())
5401 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 !");
5402 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5403 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5404 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5405 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5406 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5407 revDesc1=0; revDescIndx1=0;
5408 mDesc->tessellate2DCurve(eps);
5409 subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5410 setCoords(mDesc->getCoords());
5414 * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5415 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5416 * \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5417 * a sub-divided edge.
5418 * \throw If the coordinates array is not set.
5419 * \throw If the nodal connectivity of cells is not defined.
5420 * \throw If \a this->getMeshDimension() != 1.
5421 * \throw If \a this->getSpaceDimension() != 2.
5423 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5425 checkFullyDefined();
5426 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5427 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5428 double epsa=fabs(eps);
5429 if(epsa<std::numeric_limits<double>::min())
5430 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve : epsilon is null ! Please specify a higher epsilon. If too tiny it can lead to a huge amount of nodes and memory !");
5431 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5432 int nbCells=getNumberOfCells();
5433 int nbNodes=getNumberOfNodes();
5434 const int *conn=_nodal_connec->getConstPointer();
5435 const int *connI=_nodal_connec_index->getConstPointer();
5436 const double *coords=_coords->getConstPointer();
5437 std::vector<double> addCoo;
5438 std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5439 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5440 newConnI->alloc(nbCells+1,1);
5441 int *newConnIPtr=newConnI->getPointer();
5444 INTERP_KERNEL::Node *tmp2[3];
5445 std::set<INTERP_KERNEL::NormalizedCellType> types;
5446 for(int i=0;i<nbCells;i++,newConnIPtr++)
5448 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5449 if(cm.isQuadratic())
5450 {//assert(connI[i+1]-connI[i]-1==3)
5451 tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5452 tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5453 tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5454 tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5455 INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5458 eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5459 types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5461 newConnIPtr[1]=(int)newConn.size();
5465 types.insert(INTERP_KERNEL::NORM_SEG2);
5466 newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5467 newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5468 newConnIPtr[1]=newConnIPtr[0]+3;
5473 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5474 newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5475 newConnIPtr[1]=newConnIPtr[0]+3;
5478 if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5481 DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5482 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5483 newConnArr->alloc((int)newConn.size(),1);
5484 std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5485 DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5486 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5487 newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5488 double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5489 std::copy(addCoo.begin(),addCoo.end(),work);
5490 DataArrayDouble::SetArrayIn(newCoords,_coords);
5495 * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5496 * In addition, returns an array mapping new cells to old ones. <br>
5497 * This method typically increases the number of cells in \a this mesh
5498 * but the number of nodes remains \b unchanged.
5499 * That's why the 3D splitting policies
5500 * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5501 * \param [in] policy - specifies a pattern used for splitting.
5502 * The semantic of \a policy is:
5503 * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5504 * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5505 * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8 into 5 TETRA4 (for 3D mesh only).
5506 * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8 into 6 TETRA4 (for 3D mesh only).
5507 * \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5508 * an id of old cell producing it. The caller is to delete this array using
5509 * decrRef() as it is no more needed.
5510 * \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5511 * \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5512 * and \a this->getMeshDimension() != 3.
5513 * \throw If \a policy is not one of the four discussed above.
5514 * \throw If the nodal connectivity of cells is not defined.
5515 * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5517 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5522 return simplexizePol0();
5524 return simplexizePol1();
5525 case (int) INTERP_KERNEL::PLANAR_FACE_5:
5526 return simplexizePlanarFace5();
5527 case (int) INTERP_KERNEL::PLANAR_FACE_6:
5528 return simplexizePlanarFace6();
5530 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)");
5535 * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5536 * - 1D: INTERP_KERNEL::NORM_SEG2
5537 * - 2D: INTERP_KERNEL::NORM_TRI3
5538 * - 3D: INTERP_KERNEL::NORM_TETRA4.
5540 * This method is useful for users that need to use P1 field services as
5541 * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5542 * All these methods need mesh support containing only simplex cells.
5543 * \return bool - \c true if there are only simplex cells in \a this mesh.
5544 * \throw If the coordinates array is not set.
5545 * \throw If the nodal connectivity of cells is not defined.
5546 * \throw If \a this->getMeshDimension() < 1.
5548 bool MEDCouplingUMesh::areOnlySimplexCells() const
5550 checkFullyDefined();
5551 int mdim=getMeshDimension();
5552 if(mdim<1 || mdim>3)
5553 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5554 int nbCells=getNumberOfCells();
5555 const int *conn=_nodal_connec->getConstPointer();
5556 const int *connI=_nodal_connec_index->getConstPointer();
5557 for(int i=0;i<nbCells;i++)
5559 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5567 * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5569 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5571 checkConnectivityFullyDefined();
5572 if(getMeshDimension()!=2)
5573 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5574 int nbOfCells=getNumberOfCells();
5575 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5576 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5577 ret->alloc(nbOfCells+nbOfCutCells,1);
5578 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5579 int *retPt=ret->getPointer();
5580 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5581 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5582 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5583 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5584 int *pt=newConn->getPointer();
5585 int *ptI=newConnI->getPointer();
5587 const int *oldc=_nodal_connec->getConstPointer();
5588 const int *ci=_nodal_connec_index->getConstPointer();
5589 for(int i=0;i<nbOfCells;i++,ci++)
5591 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5593 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5594 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5595 pt=std::copy(tmp,tmp+8,pt);
5604 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5605 ptI[1]=ptI[0]+ci[1]-ci[0];
5610 _nodal_connec->decrRef();
5611 _nodal_connec=newConn.retn();
5612 _nodal_connec_index->decrRef();
5613 _nodal_connec_index=newConnI.retn();
5620 * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5622 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5624 checkConnectivityFullyDefined();
5625 if(getMeshDimension()!=2)
5626 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5627 int nbOfCells=getNumberOfCells();
5628 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5629 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5630 ret->alloc(nbOfCells+nbOfCutCells,1);
5631 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5632 int *retPt=ret->getPointer();
5633 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5634 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5635 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5636 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5637 int *pt=newConn->getPointer();
5638 int *ptI=newConnI->getPointer();
5640 const int *oldc=_nodal_connec->getConstPointer();
5641 const int *ci=_nodal_connec_index->getConstPointer();
5642 for(int i=0;i<nbOfCells;i++,ci++)
5644 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5646 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5647 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5648 pt=std::copy(tmp,tmp+8,pt);
5657 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5658 ptI[1]=ptI[0]+ci[1]-ci[0];
5663 _nodal_connec->decrRef();
5664 _nodal_connec=newConn.retn();
5665 _nodal_connec_index->decrRef();
5666 _nodal_connec_index=newConnI.retn();
5673 * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5675 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5677 checkConnectivityFullyDefined();
5678 if(getMeshDimension()!=3)
5679 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5680 int nbOfCells=getNumberOfCells();
5681 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5682 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5683 ret->alloc(nbOfCells+4*nbOfCutCells,1);
5684 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5685 int *retPt=ret->getPointer();
5686 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5687 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5688 newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5689 newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5690 int *pt=newConn->getPointer();
5691 int *ptI=newConnI->getPointer();
5693 const int *oldc=_nodal_connec->getConstPointer();
5694 const int *ci=_nodal_connec_index->getConstPointer();
5695 for(int i=0;i<nbOfCells;i++,ci++)
5697 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5699 for(int j=0;j<5;j++,pt+=5,ptI++)
5701 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5702 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];
5709 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5710 ptI[1]=ptI[0]+ci[1]-ci[0];
5715 _nodal_connec->decrRef();
5716 _nodal_connec=newConn.retn();
5717 _nodal_connec_index->decrRef();
5718 _nodal_connec_index=newConnI.retn();
5725 * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5727 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5729 checkConnectivityFullyDefined();
5730 if(getMeshDimension()!=3)
5731 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5732 int nbOfCells=getNumberOfCells();
5733 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5734 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5735 ret->alloc(nbOfCells+5*nbOfCutCells,1);
5736 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5737 int *retPt=ret->getPointer();
5738 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5739 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5740 newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5741 newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5742 int *pt=newConn->getPointer();
5743 int *ptI=newConnI->getPointer();
5745 const int *oldc=_nodal_connec->getConstPointer();
5746 const int *ci=_nodal_connec_index->getConstPointer();
5747 for(int i=0;i<nbOfCells;i++,ci++)
5749 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5751 for(int j=0;j<6;j++,pt+=5,ptI++)
5753 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5754 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];
5761 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5762 ptI[1]=ptI[0]+ci[1]-ci[0];
5767 _nodal_connec->decrRef();
5768 _nodal_connec=newConn.retn();
5769 _nodal_connec_index->decrRef();
5770 _nodal_connec_index=newConnI.retn();
5777 * 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.
5778 * This method completly ignore coordinates.
5779 * \param nodeSubdived is the nodal connectivity of subdivision of edges
5780 * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5781 * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5782 * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5784 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5786 checkFullyDefined();
5787 if(getMeshDimension()!=2)
5788 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5789 int nbOfCells=getNumberOfCells();
5790 int *connI=_nodal_connec_index->getPointer();
5792 for(int i=0;i<nbOfCells;i++,connI++)
5794 int offset=descIndex[i];
5795 int nbOfEdges=descIndex[i+1]-offset;
5797 bool ddirect=desc[offset+nbOfEdges-1]>0;
5798 int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5799 int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5800 for(int j=0;j<nbOfEdges;j++)
5802 bool direct=desc[offset+j]>0;
5803 int edgeId=std::abs(desc[offset+j])-1;
5804 if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5806 int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5807 int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5808 int ref2=direct?id1:id2;
5811 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5812 newConnLgth+=nbOfSubNodes-1;
5817 std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5818 throw INTERP_KERNEL::Exception(oss.str().c_str());
5823 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5826 newConnLgth++;//+1 is for cell type
5827 connI[1]=newConnLgth;
5830 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5831 newConn->alloc(newConnLgth,1);
5832 int *work=newConn->getPointer();
5833 for(int i=0;i<nbOfCells;i++)
5835 *work++=INTERP_KERNEL::NORM_POLYGON;
5836 int offset=descIndex[i];
5837 int nbOfEdges=descIndex[i+1]-offset;
5838 for(int j=0;j<nbOfEdges;j++)
5840 bool direct=desc[offset+j]>0;
5841 int edgeId=std::abs(desc[offset+j])-1;
5843 work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5846 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5847 std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5848 work=std::copy(it,it+nbOfSubNodes-1,work);
5852 DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5855 _types.insert(INTERP_KERNEL::NORM_POLYGON);
5859 * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5860 * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5861 * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5862 * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5863 * so it can be useful to call mergeNodes() before calling this method.
5864 * \throw If \a this->getMeshDimension() <= 1.
5865 * \throw If the coordinates array is not set.
5866 * \throw If the nodal connectivity of cells is not defined.
5868 void MEDCouplingUMesh::convertDegeneratedCells()
5870 checkFullyDefined();
5871 if(getMeshDimension()<=1)
5872 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5873 int nbOfCells=getNumberOfCells();
5876 int initMeshLgth=getMeshLength();
5877 int *conn=_nodal_connec->getPointer();
5878 int *index=_nodal_connec_index->getPointer();
5882 for(int i=0;i<nbOfCells;i++)
5884 lgthOfCurCell=index[i+1]-posOfCurCell;
5885 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5887 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5888 conn+newPos+1,newLgth);
5889 conn[newPos]=newType;
5891 posOfCurCell=index[i+1];
5894 if(newPos!=initMeshLgth)
5895 _nodal_connec->reAlloc(newPos);
5900 * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5901 * A cell is considered to be oriented correctly if an angle between its
5902 * normal vector and a given vector is less than \c PI / \c 2.
5903 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5905 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5907 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5908 * is not cleared before filling in.
5909 * \throw If \a this->getMeshDimension() != 2.
5910 * \throw If \a this->getSpaceDimension() != 3.
5912 * \if ENABLE_EXAMPLES
5913 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5914 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5917 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
5919 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5920 throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5921 int nbOfCells=getNumberOfCells();
5922 const int *conn=_nodal_connec->getConstPointer();
5923 const int *connI=_nodal_connec_index->getConstPointer();
5924 const double *coordsPtr=_coords->getConstPointer();
5925 for(int i=0;i<nbOfCells;i++)
5927 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5928 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5930 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5931 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5938 * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5939 * considered to be oriented correctly if an angle between its normal vector and a
5940 * given vector is less than \c PI / \c 2.
5941 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5943 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5945 * \throw If \a this->getMeshDimension() != 2.
5946 * \throw If \a this->getSpaceDimension() != 3.
5948 * \if ENABLE_EXAMPLES
5949 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5950 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5953 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
5955 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5956 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5957 int nbOfCells=getNumberOfCells();
5958 int *conn=_nodal_connec->getPointer();
5959 const int *connI=_nodal_connec_index->getConstPointer();
5960 const double *coordsPtr=_coords->getConstPointer();
5961 bool isModified=false;
5962 for(int i=0;i<nbOfCells;i++)
5964 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5965 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5967 bool isQuadratic(INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic());
5968 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5973 std::vector<int> tmp(connI[i+1]-connI[i]-2);
5974 std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5975 std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5979 int sz(((int)(connI[i+1]-connI[i]-1))/2);
5980 std::vector<int> tmp0(sz-1),tmp1(sz);
5981 std::copy(conn+connI[i]+2,conn+connI[i]+1+sz,tmp0.rbegin());
5982 std::copy(conn+connI[i]+1+sz,conn+connI[i+1],tmp1.rbegin());
5983 std::copy(tmp0.begin(),tmp0.end(),conn+connI[i]+2);
5984 std::copy(tmp1.begin(),tmp1.end(),conn+connI[i]+1+sz);
5990 _nodal_connec->declareAsNew();
5995 * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5996 * oriented facets. The normal vector of the facet should point out of the cell.
5997 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5998 * is not cleared before filling in.
5999 * \throw If \a this->getMeshDimension() != 3.
6000 * \throw If \a this->getSpaceDimension() != 3.
6001 * \throw If the coordinates array is not set.
6002 * \throw If the nodal connectivity of cells is not defined.
6004 * \if ENABLE_EXAMPLES
6005 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6006 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6009 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
6011 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6012 throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
6013 int nbOfCells=getNumberOfCells();
6014 const int *conn=_nodal_connec->getConstPointer();
6015 const int *connI=_nodal_connec_index->getConstPointer();
6016 const double *coordsPtr=_coords->getConstPointer();
6017 for(int i=0;i<nbOfCells;i++)
6019 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6020 if(type==INTERP_KERNEL::NORM_POLYHED)
6022 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6029 * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6031 * \throw If \a this->getMeshDimension() != 3.
6032 * \throw If \a this->getSpaceDimension() != 3.
6033 * \throw If the coordinates array is not set.
6034 * \throw If the nodal connectivity of cells is not defined.
6035 * \throw If the reparation fails.
6037 * \if ENABLE_EXAMPLES
6038 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6039 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6041 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6043 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
6045 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6046 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6047 int nbOfCells=getNumberOfCells();
6048 int *conn=_nodal_connec->getPointer();
6049 const int *connI=_nodal_connec_index->getConstPointer();
6050 const double *coordsPtr=_coords->getConstPointer();
6051 for(int i=0;i<nbOfCells;i++)
6053 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6054 if(type==INTERP_KERNEL::NORM_POLYHED)
6058 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6059 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6061 catch(INTERP_KERNEL::Exception& e)
6063 std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6064 throw INTERP_KERNEL::Exception(oss.str().c_str());
6072 * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6073 * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6074 * according to which the first facet of the cell should be oriented to have the normal vector
6075 * pointing out of cell.
6076 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6077 * cells. The caller is to delete this array using decrRef() as it is no more
6079 * \throw If \a this->getMeshDimension() != 3.
6080 * \throw If \a this->getSpaceDimension() != 3.
6081 * \throw If the coordinates array is not set.
6082 * \throw If the nodal connectivity of cells is not defined.
6084 * \if ENABLE_EXAMPLES
6085 * \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6086 * \ref py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6088 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6090 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6092 const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6093 if(getMeshDimension()!=3)
6094 throw INTERP_KERNEL::Exception(msg);
6095 int spaceDim=getSpaceDimension();
6097 throw INTERP_KERNEL::Exception(msg);
6099 int nbOfCells=getNumberOfCells();
6100 int *conn=_nodal_connec->getPointer();
6101 const int *connI=_nodal_connec_index->getConstPointer();
6102 const double *coo=getCoords()->getConstPointer();
6103 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6104 for(int i=0;i<nbOfCells;i++)
6106 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6107 if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6109 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6111 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6112 cells->pushBackSilent(i);
6116 return cells.retn();
6120 * This method is a faster method to correct orientation of all 3D cells in \a this.
6121 * 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.
6122 * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6124 * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6125 * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons,
6127 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6129 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6130 throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6131 int nbOfCells=getNumberOfCells();
6132 int *conn=_nodal_connec->getPointer();
6133 const int *connI=_nodal_connec_index->getConstPointer();
6134 const double *coordsPtr=_coords->getConstPointer();
6135 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6136 for(int i=0;i<nbOfCells;i++)
6138 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6141 case INTERP_KERNEL::NORM_TETRA4:
6143 if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6145 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6146 ret->pushBackSilent(i);
6150 case INTERP_KERNEL::NORM_PYRA5:
6152 if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6154 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6155 ret->pushBackSilent(i);
6159 case INTERP_KERNEL::NORM_PENTA6:
6160 case INTERP_KERNEL::NORM_HEXA8:
6161 case INTERP_KERNEL::NORM_HEXGP12:
6163 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6165 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6166 ret->pushBackSilent(i);
6170 case INTERP_KERNEL::NORM_POLYHED:
6172 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6174 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6175 ret->pushBackSilent(i);
6180 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 !");
6188 * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6189 * If it is not the case an exception will be thrown.
6190 * This method is fast because the first cell of \a this is used to compute the plane.
6191 * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6192 * \param pos output of size at least 3 used to store a point owned of searched plane.
6194 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6196 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6197 throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6198 const int *conn=_nodal_connec->getConstPointer();
6199 const int *connI=_nodal_connec_index->getConstPointer();
6200 const double *coordsPtr=_coords->getConstPointer();
6201 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6202 std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6206 * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6207 * cells. Currently cells of the following types are treated:
6208 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6209 * For a cell of other type an exception is thrown.
6210 * Space dimension of a 2D mesh can be either 2 or 3.
6211 * The Edge Ratio of a cell \f$t\f$ is:
6212 * \f$\frac{|t|_\infty}{|t|_0}\f$,
6213 * where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6214 * the smallest edge lengths of \f$t\f$.
6215 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6216 * cells and one time, lying on \a this mesh. The caller is to delete this
6217 * field using decrRef() as it is no more needed.
6218 * \throw If the coordinates array is not set.
6219 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6220 * \throw If the connectivity data array has more than one component.
6221 * \throw If the connectivity data array has a named component.
6222 * \throw If the connectivity index data array has more than one component.
6223 * \throw If the connectivity index data array has a named component.
6224 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6225 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6226 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6228 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6231 int spaceDim=getSpaceDimension();
6232 int meshDim=getMeshDimension();
6233 if(spaceDim!=2 && spaceDim!=3)
6234 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6235 if(meshDim!=2 && meshDim!=3)
6236 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6237 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6239 int nbOfCells=getNumberOfCells();
6240 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6241 arr->alloc(nbOfCells,1);
6242 double *pt=arr->getPointer();
6243 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6244 const int *conn=_nodal_connec->getConstPointer();
6245 const int *connI=_nodal_connec_index->getConstPointer();
6246 const double *coo=_coords->getConstPointer();
6248 for(int i=0;i<nbOfCells;i++,pt++)
6250 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6253 case INTERP_KERNEL::NORM_TRI3:
6255 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6256 *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6259 case INTERP_KERNEL::NORM_QUAD4:
6261 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6262 *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6265 case INTERP_KERNEL::NORM_TETRA4:
6267 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6268 *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6272 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6274 conn+=connI[i+1]-connI[i];
6276 ret->setName("EdgeRatio");
6277 ret->synchronizeTimeWithSupport();
6282 * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6283 * cells. Currently cells of the following types are treated:
6284 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6285 * For a cell of other type an exception is thrown.
6286 * Space dimension of a 2D mesh can be either 2 or 3.
6287 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6288 * cells and one time, lying on \a this mesh. The caller is to delete this
6289 * field using decrRef() as it is no more needed.
6290 * \throw If the coordinates array is not set.
6291 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6292 * \throw If the connectivity data array has more than one component.
6293 * \throw If the connectivity data array has a named component.
6294 * \throw If the connectivity index data array has more than one component.
6295 * \throw If the connectivity index data array has a named component.
6296 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6297 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6298 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6300 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6303 int spaceDim=getSpaceDimension();
6304 int meshDim=getMeshDimension();
6305 if(spaceDim!=2 && spaceDim!=3)
6306 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6307 if(meshDim!=2 && meshDim!=3)
6308 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6309 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6311 int nbOfCells=getNumberOfCells();
6312 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6313 arr->alloc(nbOfCells,1);
6314 double *pt=arr->getPointer();
6315 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6316 const int *conn=_nodal_connec->getConstPointer();
6317 const int *connI=_nodal_connec_index->getConstPointer();
6318 const double *coo=_coords->getConstPointer();
6320 for(int i=0;i<nbOfCells;i++,pt++)
6322 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6325 case INTERP_KERNEL::NORM_TRI3:
6327 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6328 *pt=INTERP_KERNEL::triAspectRatio(tmp);
6331 case INTERP_KERNEL::NORM_QUAD4:
6333 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6334 *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6337 case INTERP_KERNEL::NORM_TETRA4:
6339 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6340 *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6344 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6346 conn+=connI[i+1]-connI[i];
6348 ret->setName("AspectRatio");
6349 ret->synchronizeTimeWithSupport();
6354 * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6355 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6356 * treated: INTERP_KERNEL::NORM_QUAD4.
6357 * For a cell of other type an exception is thrown.
6358 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6359 * cells and one time, lying on \a this mesh. The caller is to delete this
6360 * field using decrRef() as it is no more needed.
6361 * \throw If the coordinates array is not set.
6362 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6363 * \throw If the connectivity data array has more than one component.
6364 * \throw If the connectivity data array has a named component.
6365 * \throw If the connectivity index data array has more than one component.
6366 * \throw If the connectivity index data array has a named component.
6367 * \throw If \a this->getMeshDimension() != 2.
6368 * \throw If \a this->getSpaceDimension() != 3.
6369 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6371 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6374 int spaceDim=getSpaceDimension();
6375 int meshDim=getMeshDimension();
6377 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6379 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6380 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6382 int nbOfCells=getNumberOfCells();
6383 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6384 arr->alloc(nbOfCells,1);
6385 double *pt=arr->getPointer();
6386 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6387 const int *conn=_nodal_connec->getConstPointer();
6388 const int *connI=_nodal_connec_index->getConstPointer();
6389 const double *coo=_coords->getConstPointer();
6391 for(int i=0;i<nbOfCells;i++,pt++)
6393 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6396 case INTERP_KERNEL::NORM_QUAD4:
6398 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6399 *pt=INTERP_KERNEL::quadWarp(tmp);
6403 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6405 conn+=connI[i+1]-connI[i];
6407 ret->setName("Warp");
6408 ret->synchronizeTimeWithSupport();
6414 * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6415 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6416 * treated: INTERP_KERNEL::NORM_QUAD4.
6417 * For a cell of other type an exception is thrown.
6418 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6419 * cells and one time, lying on \a this mesh. The caller is to delete this
6420 * field using decrRef() as it is no more needed.
6421 * \throw If the coordinates array is not set.
6422 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6423 * \throw If the connectivity data array has more than one component.
6424 * \throw If the connectivity data array has a named component.
6425 * \throw If the connectivity index data array has more than one component.
6426 * \throw If the connectivity index data array has a named component.
6427 * \throw If \a this->getMeshDimension() != 2.
6428 * \throw If \a this->getSpaceDimension() != 3.
6429 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6431 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6434 int spaceDim=getSpaceDimension();
6435 int meshDim=getMeshDimension();
6437 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6439 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6440 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6442 int nbOfCells=getNumberOfCells();
6443 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6444 arr->alloc(nbOfCells,1);
6445 double *pt=arr->getPointer();
6446 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6447 const int *conn=_nodal_connec->getConstPointer();
6448 const int *connI=_nodal_connec_index->getConstPointer();
6449 const double *coo=_coords->getConstPointer();
6451 for(int i=0;i<nbOfCells;i++,pt++)
6453 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6456 case INTERP_KERNEL::NORM_QUAD4:
6458 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6459 *pt=INTERP_KERNEL::quadSkew(tmp);
6463 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6465 conn+=connI[i+1]-connI[i];
6467 ret->setName("Skew");
6468 ret->synchronizeTimeWithSupport();
6473 * This method aggregate the bbox of each cell and put it into bbox parameter.
6475 * \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)
6476 * For all other cases this input parameter is ignored.
6477 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6479 * \throw If \a this is not fully set (coordinates and connectivity).
6480 * \throw If a cell in \a this has no valid nodeId.
6481 * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6483 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6485 int mDim(getMeshDimension()),sDim(getSpaceDimension());
6486 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.
6487 return getBoundingBoxForBBTreeFast();
6488 if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6490 bool presenceOfQuadratic(false);
6491 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6493 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6494 if(cm.isQuadratic())
6495 presenceOfQuadratic=true;
6497 if(!presenceOfQuadratic)
6498 return getBoundingBoxForBBTreeFast();
6499 if(mDim==2 && sDim==2)
6500 return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6502 return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6504 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) !");
6508 * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6509 * So meshes having quadratic cells the computed bounding boxes can be invalid !
6511 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6513 * \throw If \a this is not fully set (coordinates and connectivity).
6514 * \throw If a cell in \a this has no valid nodeId.
6516 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6518 checkFullyDefined();
6519 int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6520 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6521 double *bbox(ret->getPointer());
6522 for(int i=0;i<nbOfCells*spaceDim;i++)
6524 bbox[2*i]=std::numeric_limits<double>::max();
6525 bbox[2*i+1]=-std::numeric_limits<double>::max();
6527 const double *coordsPtr(_coords->getConstPointer());
6528 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6529 for(int i=0;i<nbOfCells;i++)
6531 int offset=connI[i]+1;
6532 int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6533 for(int j=0;j<nbOfNodesForCell;j++)
6535 int nodeId=conn[offset+j];
6536 if(nodeId>=0 && nodeId<nbOfNodes)
6538 for(int k=0;k<spaceDim;k++)
6540 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6541 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6548 std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6549 throw INTERP_KERNEL::Exception(oss.str().c_str());
6556 * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6557 * useful for 2D meshes having quadratic cells
6558 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6559 * the two extremities of the arc of circle).
6561 * \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)
6562 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6563 * \throw If \a this is not fully defined.
6564 * \throw If \a this is not a mesh with meshDimension equal to 2.
6565 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6566 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6568 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6570 checkFullyDefined();
6571 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6572 if(spaceDim!=2 || mDim!=2)
6573 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!");
6574 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6575 double *bbox(ret->getPointer());
6576 const double *coords(_coords->getConstPointer());
6577 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6578 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6580 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6581 int sz(connI[1]-connI[0]-1);
6582 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6583 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6584 INTERP_KERNEL::QuadraticPolygon *pol(0);
6585 for(int j=0;j<sz;j++)
6587 int nodeId(conn[*connI+1+j]);
6588 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6590 if(!cm.isQuadratic())
6591 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6593 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6594 INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6595 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax();
6601 * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6602 * useful for 2D meshes having quadratic cells
6603 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6604 * the two extremities of the arc of circle).
6606 * \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)
6607 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6608 * \throw If \a this is not fully defined.
6609 * \throw If \a this is not a mesh with meshDimension equal to 1.
6610 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6611 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6613 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6615 checkFullyDefined();
6616 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6617 if(spaceDim!=2 || mDim!=1)
6618 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!");
6619 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6620 double *bbox(ret->getPointer());
6621 const double *coords(_coords->getConstPointer());
6622 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6623 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6625 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6626 int sz(connI[1]-connI[0]-1);
6627 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6628 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6629 INTERP_KERNEL::Edge *edge(0);
6630 for(int j=0;j<sz;j++)
6632 int nodeId(conn[*connI+1+j]);
6633 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6635 if(!cm.isQuadratic())
6636 edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6638 edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6639 const INTERP_KERNEL::Bounds& b(edge->getBounds());
6640 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6647 namespace ParaMEDMEMImpl
6652 ConnReader(const int *c, int val):_conn(c),_val(val) { }
6653 bool operator() (const int& pos) { return _conn[pos]!=_val; }
6662 ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6663 bool operator() (const int& pos) { return _conn[pos]==_val; }
6673 * This method expects that \a this is sorted by types. If not an exception will be thrown.
6674 * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6675 * \a this is composed in cell types.
6676 * The returned array is of size 3*n where n is the number of different types present in \a this.
6677 * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here.
6678 * This parameter is kept only for compatibility with other methode listed above.
6680 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6682 checkConnectivityFullyDefined();
6683 const int *conn=_nodal_connec->getConstPointer();
6684 const int *connI=_nodal_connec_index->getConstPointer();
6685 const int *work=connI;
6686 int nbOfCells=getNumberOfCells();
6687 std::size_t n=getAllGeoTypes().size();
6688 std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6689 std::set<INTERP_KERNEL::NormalizedCellType> types;
6690 for(std::size_t i=0;work!=connI+nbOfCells;i++)
6692 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6693 if(types.find(typ)!=types.end())
6695 std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6696 oss << " is not contiguous !";
6697 throw INTERP_KERNEL::Exception(oss.str().c_str());
6701 const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6702 ret[3*i+1]=(int)std::distance(work,work2);
6709 * This method is used to check that this has contiguous cell type in same order than described in \a code.
6710 * only for types cell, type node is not managed.
6711 * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6712 * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6713 * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6714 * If 2 or more same geometric type is in \a code and exception is thrown too.
6716 * This method firstly checks
6717 * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6718 * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6719 * an exception is thrown too.
6721 * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6722 * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown
6723 * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6725 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6728 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6729 std::size_t sz=code.size();
6732 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6733 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6735 bool isNoPflUsed=true;
6736 for(std::size_t i=0;i<n;i++)
6737 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6739 types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6741 if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6742 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6743 isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6746 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6749 if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6750 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6751 if(types.size()==_types.size())
6754 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6756 int *retPtr=ret->getPointer();
6757 const int *connI=_nodal_connec_index->getConstPointer();
6758 const int *conn=_nodal_connec->getConstPointer();
6759 int nbOfCells=getNumberOfCells();
6762 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6764 i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6765 int offset=(int)std::distance(connI,i);
6766 const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6767 int nbOfCellsOfCurType=(int)std::distance(i,j);
6768 if(code[3*kk+2]==-1)
6769 for(int k=0;k<nbOfCellsOfCurType;k++)
6773 int idInIdsPerType=code[3*kk+2];
6774 if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6776 const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6779 zePfl->checkAllocated();
6780 if(zePfl->getNumberOfComponents()==1)
6782 for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6784 if(*k>=0 && *k<nbOfCellsOfCurType)
6785 *retPtr=(*k)+offset;
6788 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6789 oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6790 throw INTERP_KERNEL::Exception(oss.str().c_str());
6795 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6798 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6802 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6803 oss << " should be in [0," << idsPerType.size() << ") !";
6804 throw INTERP_KERNEL::Exception(oss.str().c_str());
6813 * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6814 * 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.
6815 * 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.
6816 * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6818 * \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.
6819 * \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,
6820 * \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6821 * \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.
6822 * This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6823 * \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
6825 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6828 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6829 if(profile->getNumberOfComponents()!=1)
6830 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6831 checkConnectivityFullyDefined();
6832 const int *conn=_nodal_connec->getConstPointer();
6833 const int *connI=_nodal_connec_index->getConstPointer();
6834 int nbOfCells=getNumberOfCells();
6835 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6836 std::vector<int> typeRangeVals(1);
6837 for(const int *i=connI;i!=connI+nbOfCells;)
6839 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6840 if(std::find(types.begin(),types.end(),curType)!=types.end())
6842 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6844 types.push_back(curType);
6845 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6846 typeRangeVals.push_back((int)std::distance(connI,i));
6849 DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6850 profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6851 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6852 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6853 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6855 int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6856 code.resize(3*nbOfCastsFinal);
6857 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6858 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6859 for(int i=0;i<nbOfCastsFinal;i++)
6861 int castId=castsPresent->getIJ(i,0);
6862 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6863 idsInPflPerType2.push_back(tmp3);
6864 code[3*i]=(int)types[castId];
6865 code[3*i+1]=tmp3->getNumberOfTuples();
6866 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6867 if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6869 tmp4->copyStringInfoFrom(*profile);
6870 idsPerType2.push_back(tmp4);
6871 code[3*i+2]=(int)idsPerType2.size()-1;
6878 std::size_t sz2=idsInPflPerType2.size();
6879 idsInPflPerType.resize(sz2);
6880 for(std::size_t i=0;i<sz2;i++)
6882 DataArrayInt *locDa=idsInPflPerType2[i];
6884 idsInPflPerType[i]=locDa;
6886 std::size_t sz=idsPerType2.size();
6887 idsPerType.resize(sz);
6888 for(std::size_t i=0;i<sz;i++)
6890 DataArrayInt *locDa=idsPerType2[i];
6892 idsPerType[i]=locDa;
6897 * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6898 * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6899 * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6900 * 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.
6902 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
6904 checkFullyDefined();
6905 nM1LevMesh->checkFullyDefined();
6906 if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6907 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6908 if(_coords!=nM1LevMesh->getCoords())
6909 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6910 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6911 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6912 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6913 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6914 desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6915 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6916 tmp->setConnectivity(tmp0,tmp1);
6917 tmp->renumberCells(ret0->getConstPointer(),false);
6918 revDesc=tmp->getNodalConnectivity();
6919 revDescIndx=tmp->getNodalConnectivityIndex();
6920 DataArrayInt *ret=0;
6921 if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6924 ret->getMaxValue(tmp2);
6926 std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6927 throw INTERP_KERNEL::Exception(oss.str().c_str());
6932 revDescIndx->incrRef();
6935 meshnM1Old2New=ret0;
6940 * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6941 * necessary for writing the mesh to MED file. Additionally returns a permutation array
6942 * in "Old to New" mode.
6943 * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6944 * this array using decrRef() as it is no more needed.
6945 * \throw If the nodal connectivity of cells is not defined.
6947 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
6949 checkConnectivityFullyDefined();
6950 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6951 renumberCells(ret->getConstPointer(),false);
6956 * This methods checks that cells are sorted by their types.
6957 * This method makes asumption (no check) that connectivity is correctly set before calling.
6959 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6961 checkFullyDefined();
6962 const int *conn=_nodal_connec->getConstPointer();
6963 const int *connI=_nodal_connec_index->getConstPointer();
6964 int nbOfCells=getNumberOfCells();
6965 std::set<INTERP_KERNEL::NormalizedCellType> types;
6966 for(const int *i=connI;i!=connI+nbOfCells;)
6968 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6969 if(types.find(curType)!=types.end())
6971 types.insert(curType);
6972 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6978 * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6979 * The geometric type order is specified by MED file.
6981 * \sa MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6983 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
6985 return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6989 * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6990 * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
6991 * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6992 * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6994 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6996 checkFullyDefined();
6997 const int *conn=_nodal_connec->getConstPointer();
6998 const int *connI=_nodal_connec_index->getConstPointer();
6999 int nbOfCells=getNumberOfCells();
7003 std::set<INTERP_KERNEL::NormalizedCellType> sg;
7004 for(const int *i=connI;i!=connI+nbOfCells;)
7006 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7007 const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
7008 if(isTypeExists!=orderEnd)
7010 int pos=(int)std::distance(orderBg,isTypeExists);
7014 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7018 if(sg.find(curType)==sg.end())
7020 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7031 * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
7032 * 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
7033 * 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'.
7035 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
7037 checkConnectivityFullyDefined();
7038 int nbOfCells=getNumberOfCells();
7039 const int *conn=_nodal_connec->getConstPointer();
7040 const int *connI=_nodal_connec_index->getConstPointer();
7041 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
7042 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
7043 tmpa->alloc(nbOfCells,1);
7044 tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
7045 tmpb->fillWithZero();
7046 int *tmp=tmpa->getPointer();
7047 int *tmp2=tmpb->getPointer();
7048 for(const int *i=connI;i!=connI+nbOfCells;i++)
7050 const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
7053 int pos=(int)std::distance(orderBg,where);
7055 tmp[std::distance(connI,i)]=pos;
7059 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
7060 std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
7061 oss << " has a type " << cm.getRepr() << " not in input array of type !";
7062 throw INTERP_KERNEL::Exception(oss.str().c_str());
7065 nbPerType=tmpb.retn();
7070 * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7072 * \return a new object containing the old to new correspondance.
7074 * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7076 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7078 return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7082 * 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.
7083 * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7084 * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7085 * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7087 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7089 DataArrayInt *nbPerType=0;
7090 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7091 nbPerType->decrRef();
7092 return tmpa->buildPermArrPerLevel();
7096 * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7097 * The number of cells remains unchanged after the call of this method.
7098 * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7099 * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7101 * \return the array giving the correspondance old to new.
7103 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7105 checkFullyDefined();
7107 const int *conn=_nodal_connec->getConstPointer();
7108 const int *connI=_nodal_connec_index->getConstPointer();
7109 int nbOfCells=getNumberOfCells();
7110 std::vector<INTERP_KERNEL::NormalizedCellType> types;
7111 for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7112 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7114 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7115 types.push_back(curType);
7116 for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7118 DataArrayInt *ret=DataArrayInt::New();
7119 ret->alloc(nbOfCells,1);
7120 int *retPtr=ret->getPointer();
7121 std::fill(retPtr,retPtr+nbOfCells,-1);
7123 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7125 for(const int *i=connI;i!=connI+nbOfCells;i++)
7126 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7127 retPtr[std::distance(connI,i)]=newCellId++;
7129 renumberCells(retPtr,false);
7134 * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7135 * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7136 * This method makes asumption that connectivity is correctly set before calling.
7138 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7140 checkConnectivityFullyDefined();
7141 const int *conn=_nodal_connec->getConstPointer();
7142 const int *connI=_nodal_connec_index->getConstPointer();
7143 int nbOfCells=getNumberOfCells();
7144 std::vector<MEDCouplingUMesh *> ret;
7145 for(const int *i=connI;i!=connI+nbOfCells;)
7147 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7148 int beginCellId=(int)std::distance(connI,i);
7149 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7150 int endCellId=(int)std::distance(connI,i);
7151 int sz=endCellId-beginCellId;
7152 int *cells=new int[sz];
7153 for(int j=0;j<sz;j++)
7154 cells[j]=beginCellId+j;
7155 MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7163 * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7164 * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7165 * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7167 * \return a newly allocated instance, that the caller must manage.
7168 * \throw If \a this contains more than one geometric type.
7169 * \throw If the nodal connectivity of \a this is not fully defined.
7170 * \throw If the internal data is not coherent.
7172 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7174 checkConnectivityFullyDefined();
7175 if(_types.size()!=1)
7176 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7177 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7178 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7179 ret->setCoords(getCoords());
7180 MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7183 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7184 retC->setNodalConnectivity(c);
7188 MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7190 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7191 DataArrayInt *c=0,*ci=0;
7192 convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7193 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7194 retD->setNodalConnectivity(cs,cis);
7199 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7201 checkConnectivityFullyDefined();
7202 if(_types.size()!=1)
7203 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7204 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7205 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7208 std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7209 oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7210 throw INTERP_KERNEL::Exception(oss.str().c_str());
7212 int nbCells=getNumberOfCells();
7214 int nbNodesPerCell=(int)cm.getNumberOfNodes();
7215 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7216 int *outPtr=connOut->getPointer();
7217 const int *conn=_nodal_connec->begin();
7218 const int *connI=_nodal_connec_index->begin();
7220 for(int i=0;i<nbCells;i++,connI++)
7222 if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7223 outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7226 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 << ") !";
7227 throw INTERP_KERNEL::Exception(oss.str().c_str());
7230 return connOut.retn();
7233 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7235 static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7236 checkConnectivityFullyDefined();
7237 if(_types.size()!=1)
7238 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7239 int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7241 throw INTERP_KERNEL::Exception(msg0);
7242 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7243 c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7244 int *cp(c->getPointer()),*cip(ci->getPointer());
7245 const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7247 for(int i=0;i<nbCells;i++,cip++,incip++)
7249 int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7250 int delta(stop-strt);
7253 if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7254 cp=std::copy(incp+strt,incp+stop,cp);
7256 throw INTERP_KERNEL::Exception(msg0);
7259 throw INTERP_KERNEL::Exception(msg0);
7260 cip[1]=cip[0]+delta;
7262 nodalConn=c.retn(); nodalConnIndex=ci.retn();
7266 * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7267 * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7268 * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7269 * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7270 * are not used here to avoid the build of big permutation array.
7272 * \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
7273 * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7274 * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7275 * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7276 * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7277 * output array gives for each chunck of same type the corresponding mesh id in \b ms.
7278 * \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
7279 * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7281 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7282 DataArrayInt *&szOfCellGrpOfSameType,
7283 DataArrayInt *&idInMsOfCellGrpOfSameType)
7285 std::vector<const MEDCouplingUMesh *> ms2;
7286 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7289 (*it)->checkConnectivityFullyDefined();
7293 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7294 const DataArrayDouble *refCoo=ms2[0]->getCoords();
7295 int meshDim=ms2[0]->getMeshDimension();
7296 std::vector<const MEDCouplingUMesh *> m1ssm;
7297 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7299 std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7300 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7302 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7303 ret1->alloc(0,1); ret2->alloc(0,1);
7304 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7306 if(meshDim!=(*it)->getMeshDimension())
7307 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7308 if(refCoo!=(*it)->getCoords())
7309 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7310 std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7311 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7312 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7313 for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7315 MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7316 m1ssmSingleAuto.push_back(singleCell);
7317 m1ssmSingle.push_back(singleCell);
7318 ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7321 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7322 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7323 std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7324 for(std::size_t i=0;i<m1ssm.size();i++)
7325 m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7326 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7327 szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7328 idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7333 * This method returns a newly created DataArrayInt instance.
7334 * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7336 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7338 checkFullyDefined();
7339 const int *conn=_nodal_connec->getConstPointer();
7340 const int *connIndex=_nodal_connec_index->getConstPointer();
7341 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7342 for(const int *w=begin;w!=end;w++)
7343 if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7344 ret->pushBackSilent(*w);
7349 * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7350 * are in [0:getNumberOfCells())
7352 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7354 checkFullyDefined();
7355 const int *conn=_nodal_connec->getConstPointer();
7356 const int *connI=_nodal_connec_index->getConstPointer();
7357 int nbOfCells=getNumberOfCells();
7358 std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7359 int *tmp=new int[nbOfCells];
7360 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7363 for(const int *i=connI;i!=connI+nbOfCells;i++)
7364 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7365 tmp[std::distance(connI,i)]=j++;
7367 DataArrayInt *ret=DataArrayInt::New();
7368 ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7369 ret->copyStringInfoFrom(*da);
7370 int *retPtr=ret->getPointer();
7371 const int *daPtr=da->getConstPointer();
7372 int nbOfElems=da->getNbOfElems();
7373 for(int k=0;k<nbOfElems;k++)
7374 retPtr[k]=tmp[daPtr[k]];
7380 * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7381 * This method \b works \b for mesh sorted by type.
7382 * cells whose ids is in 'idsPerGeoType' array.
7383 * This method conserves coords and name of mesh.
7385 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7387 std::vector<int> code=getDistributionOfTypes();
7388 std::size_t nOfTypesInThis=code.size()/3;
7389 int sz=0,szOfType=0;
7390 for(std::size_t i=0;i<nOfTypesInThis;i++)
7395 szOfType=code[3*i+1];
7397 for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7398 if(*work<0 || *work>=szOfType)
7400 std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7401 oss << ". It should be in [0," << szOfType << ") !";
7402 throw INTERP_KERNEL::Exception(oss.str().c_str());
7404 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7405 int *idsPtr=idsTokeep->getPointer();
7407 for(std::size_t i=0;i<nOfTypesInThis;i++)
7410 for(int j=0;j<code[3*i+1];j++)
7413 idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7414 offset+=code[3*i+1];
7416 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7417 ret->copyTinyInfoFrom(this);
7422 * This method returns a vector of size 'this->getNumberOfCells()'.
7423 * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7425 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7427 int ncell=getNumberOfCells();
7428 std::vector<bool> ret(ncell);
7429 const int *cI=getNodalConnectivityIndex()->getConstPointer();
7430 const int *c=getNodalConnectivity()->getConstPointer();
7431 for(int i=0;i<ncell;i++)
7433 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7434 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7435 ret[i]=cm.isQuadratic();
7441 * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7443 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7445 if(other->getType()!=UNSTRUCTURED)
7446 throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7447 const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7448 return MergeUMeshes(this,otherC);
7452 * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7453 * computed by averaging coordinates of cell nodes, so this method is not a right
7454 * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7455 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7456 * this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7457 * components. The caller is to delete this array using decrRef() as it is
7459 * \throw If the coordinates array is not set.
7460 * \throw If the nodal connectivity of cells is not defined.
7461 * \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7463 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7465 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7466 int spaceDim=getSpaceDimension();
7467 int nbOfCells=getNumberOfCells();
7468 ret->alloc(nbOfCells,spaceDim);
7469 ret->copyStringInfoFrom(*getCoords());
7470 double *ptToFill=ret->getPointer();
7471 const int *nodal=_nodal_connec->getConstPointer();
7472 const int *nodalI=_nodal_connec_index->getConstPointer();
7473 const double *coor=_coords->getConstPointer();
7474 for(int i=0;i<nbOfCells;i++)
7476 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7477 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7484 * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7485 * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the
7487 * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned
7488 * DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7490 * \sa MEDCouplingUMesh::getBarycenterAndOwner
7491 * \throw If \a this is not fully defined (coordinates and connectivity)
7492 * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7494 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7496 checkFullyDefined();
7497 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7498 int spaceDim=getSpaceDimension();
7499 int nbOfCells=getNumberOfCells();
7500 int nbOfNodes=getNumberOfNodes();
7501 ret->alloc(nbOfCells,spaceDim);
7502 double *ptToFill=ret->getPointer();
7503 const int *nodal=_nodal_connec->getConstPointer();
7504 const int *nodalI=_nodal_connec_index->getConstPointer();
7505 const double *coor=_coords->getConstPointer();
7506 for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7508 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7509 std::fill(ptToFill,ptToFill+spaceDim,0.);
7510 if(type!=INTERP_KERNEL::NORM_POLYHED)
7512 for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7514 if(*conn>=0 && *conn<nbOfNodes)
7515 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7518 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," << nbOfNodes << ") !";
7519 throw INTERP_KERNEL::Exception(oss.str().c_str());
7522 int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7523 if(nbOfNodesInCell>0)
7524 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7527 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7528 throw INTERP_KERNEL::Exception(oss.str().c_str());
7533 std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7535 for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7537 if(*it>=0 && *it<nbOfNodes)
7538 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7541 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," << nbOfNodes << ") !";
7542 throw INTERP_KERNEL::Exception(oss.str().c_str());
7546 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7549 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7550 throw INTERP_KERNEL::Exception(oss.str().c_str());
7558 * Returns a new DataArrayDouble holding barycenters of specified cells. The
7559 * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7560 * are specified via an array of cell ids.
7561 * \warning Validity of the specified cell ids is not checked!
7562 * Valid range is [ 0, \a this->getNumberOfCells() ).
7563 * \param [in] begin - an array of cell ids of interest.
7564 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7565 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7566 * end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7567 * caller is to delete this array using decrRef() as it is no more needed.
7568 * \throw If the coordinates array is not set.
7569 * \throw If the nodal connectivity of cells is not defined.
7571 * \if ENABLE_EXAMPLES
7572 * \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7573 * \ref py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7576 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7578 DataArrayDouble *ret=DataArrayDouble::New();
7579 int spaceDim=getSpaceDimension();
7580 int nbOfTuple=(int)std::distance(begin,end);
7581 ret->alloc(nbOfTuple,spaceDim);
7582 double *ptToFill=ret->getPointer();
7583 double *tmp=new double[spaceDim];
7584 const int *nodal=_nodal_connec->getConstPointer();
7585 const int *nodalI=_nodal_connec_index->getConstPointer();
7586 const double *coor=_coords->getConstPointer();
7587 for(const int *w=begin;w!=end;w++)
7589 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7590 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7598 * 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".
7599 * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7600 * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7601 * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7602 * This method is useful to detect 2D cells in 3D space that are not coplanar.
7604 * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7605 * \throw If spaceDim!=3 or meshDim!=2.
7606 * \throw If connectivity of \a this is invalid.
7607 * \throw If connectivity of a cell in \a this points to an invalid node.
7609 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7611 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7612 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7613 if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7614 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7615 ret->alloc(nbOfCells,4);
7616 double *retPtr(ret->getPointer());
7617 const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7618 const double *coor(_coords->begin());
7619 for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7621 double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7622 if(nodalI[1]-nodalI[0]>=3)
7624 for(int j=0;j<3;j++)
7626 int nodeId(nodal[nodalI[0]+1+j]);
7627 if(nodeId>=0 && nodeId<nbOfNodes)
7628 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7631 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7632 throw INTERP_KERNEL::Exception(oss.str().c_str());
7638 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7639 throw INTERP_KERNEL::Exception(oss.str().c_str());
7641 INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7642 retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7648 * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7651 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7654 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7655 da->checkAllocated();
7656 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7658 int nbOfTuples=da->getNumberOfTuples();
7659 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7660 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7661 c->alloc(2*nbOfTuples,1);
7662 cI->alloc(nbOfTuples+1,1);
7663 int *cp=c->getPointer();
7664 int *cip=cI->getPointer();
7666 for(int i=0;i<nbOfTuples;i++)
7668 *cp++=INTERP_KERNEL::NORM_POINT1;
7672 ret->setConnectivity(c,cI,true);
7676 * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7677 * Cells and nodes of
7678 * the first mesh precede cells and nodes of the second mesh within the result mesh.
7679 * \param [in] mesh1 - the first mesh.
7680 * \param [in] mesh2 - the second mesh.
7681 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7682 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7683 * is no more needed.
7684 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7685 * \throw If the coordinates array is not set in none of the meshes.
7686 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7687 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7689 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7691 std::vector<const MEDCouplingUMesh *> tmp(2);
7692 tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7693 return MergeUMeshes(tmp);
7697 * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7698 * Cells and nodes of
7699 * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7700 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7701 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7702 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7703 * is no more needed.
7704 * \throw If \a a.size() == 0.
7705 * \throw If \a a[ *i* ] == NULL.
7706 * \throw If the coordinates array is not set in none of the meshes.
7707 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7708 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7710 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7712 std::size_t sz=a.size();
7714 return MergeUMeshesLL(a);
7715 for(std::size_t ii=0;ii<sz;ii++)
7718 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7719 throw INTERP_KERNEL::Exception(oss.str().c_str());
7721 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7722 std::vector< const MEDCouplingUMesh * > aa(sz);
7724 for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7726 const MEDCouplingUMesh *cur=a[i];
7727 const DataArrayDouble *coo=cur->getCoords();
7729 spaceDim=coo->getNumberOfComponents();
7732 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7733 for(std::size_t i=0;i<sz;i++)
7735 bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7738 return MergeUMeshesLL(aa);
7743 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7746 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7747 std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7748 int meshDim=(*it)->getMeshDimension();
7749 int nbOfCells=(*it)->getNumberOfCells();
7750 int meshLgth=(*it++)->getMeshLength();
7751 for(;it!=a.end();it++)
7753 if(meshDim!=(*it)->getMeshDimension())
7754 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7755 nbOfCells+=(*it)->getNumberOfCells();
7756 meshLgth+=(*it)->getMeshLength();
7758 std::vector<const MEDCouplingPointSet *> aps(a.size());
7759 std::copy(a.begin(),a.end(),aps.begin());
7760 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7761 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7762 ret->setCoords(pts);
7763 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7764 c->alloc(meshLgth,1);
7765 int *cPtr=c->getPointer();
7766 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7767 cI->alloc(nbOfCells+1,1);
7768 int *cIPtr=cI->getPointer();
7772 for(it=a.begin();it!=a.end();it++)
7774 int curNbOfCell=(*it)->getNumberOfCells();
7775 const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7776 const int *curC=(*it)->_nodal_connec->getConstPointer();
7777 cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7778 for(int j=0;j<curNbOfCell;j++)
7780 const int *src=curC+curCI[j];
7782 for(;src!=curC+curCI[j+1];src++,cPtr++)
7790 offset+=curCI[curNbOfCell];
7791 offset2+=(*it)->getNumberOfNodes();
7794 ret->setConnectivity(c,cI,true);
7801 * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7802 * dimension and sharing the node coordinates array.
7803 * All cells of the first mesh precede all cells of the second mesh
7804 * within the result mesh.
7805 * \param [in] mesh1 - the first mesh.
7806 * \param [in] mesh2 - the second mesh.
7807 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7808 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7809 * is no more needed.
7810 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7811 * \throw If the meshes do not share the node coordinates array.
7812 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7813 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7815 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7817 std::vector<const MEDCouplingUMesh *> tmp(2);
7818 tmp[0]=mesh1; tmp[1]=mesh2;
7819 return MergeUMeshesOnSameCoords(tmp);
7823 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7824 * dimension and sharing the node coordinates array.
7825 * All cells of the *i*-th mesh precede all cells of the
7826 * (*i*+1)-th mesh within the result mesh.
7827 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7828 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7829 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7830 * is no more needed.
7831 * \throw If \a a.size() == 0.
7832 * \throw If \a a[ *i* ] == NULL.
7833 * \throw If the meshes do not share the node coordinates array.
7834 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7835 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7837 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7840 throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7841 for(std::size_t ii=0;ii<meshes.size();ii++)
7844 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7845 throw INTERP_KERNEL::Exception(oss.str().c_str());
7847 const DataArrayDouble *coords=meshes.front()->getCoords();
7848 int meshDim=meshes.front()->getMeshDimension();
7849 std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7851 int meshIndexLgth=0;
7852 for(;iter!=meshes.end();iter++)
7854 if(coords!=(*iter)->getCoords())
7855 throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7856 if(meshDim!=(*iter)->getMeshDimension())
7857 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7858 meshLgth+=(*iter)->getMeshLength();
7859 meshIndexLgth+=(*iter)->getNumberOfCells();
7861 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7862 nodal->alloc(meshLgth,1);
7863 int *nodalPtr=nodal->getPointer();
7864 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7865 nodalIndex->alloc(meshIndexLgth+1,1);
7866 int *nodalIndexPtr=nodalIndex->getPointer();
7868 for(iter=meshes.begin();iter!=meshes.end();iter++)
7870 const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7871 const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7872 int nbOfCells=(*iter)->getNumberOfCells();
7873 int meshLgth2=(*iter)->getMeshLength();
7874 nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7875 if(iter!=meshes.begin())
7876 nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7878 nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7881 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7882 ret->setName("merge");
7883 ret->setMeshDimension(meshDim);
7884 ret->setConnectivity(nodal,nodalIndex,true);
7885 ret->setCoords(coords);
7890 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7891 * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7892 * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7893 * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7894 * New" mode are returned for each input mesh.
7895 * \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7896 * \param [in] compType - specifies a cell comparison technique. For meaning of its
7897 * valid values [0,1,2], see zipConnectivityTraducer().
7898 * \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7899 * meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7900 * mesh. The caller is to delete each of the arrays using decrRef() as it is
7902 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7903 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7904 * is no more needed.
7905 * \throw If \a meshes.size() == 0.
7906 * \throw If \a meshes[ *i* ] == NULL.
7907 * \throw If the meshes do not share the node coordinates array.
7908 * \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7909 * \throw If the \a meshes are of different dimension (getMeshDimension()).
7910 * \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7911 * \throw If the nodal connectivity any of \a meshes includes an invalid id.
7913 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7915 //All checks are delegated to MergeUMeshesOnSameCoords
7916 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7917 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7918 corr.resize(meshes.size());
7919 std::size_t nbOfMeshes=meshes.size();
7921 const int *o2nPtr=o2n->getConstPointer();
7922 for(std::size_t i=0;i<nbOfMeshes;i++)
7924 DataArrayInt *tmp=DataArrayInt::New();
7925 int curNbOfCells=meshes[i]->getNumberOfCells();
7926 tmp->alloc(curNbOfCells,1);
7927 std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7928 offset+=curNbOfCells;
7929 tmp->setName(meshes[i]->getName());
7936 * Makes all given meshes share the nodal connectivity array. The common connectivity
7937 * array is created by concatenating the connectivity arrays of all given meshes. All
7938 * the given meshes must be of the same space dimension but dimension of cells **can
7939 * differ**. This method is particulary useful in MEDLoader context to build a \ref
7940 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7941 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7942 * \param [in,out] meshes - a vector of meshes to update.
7943 * \throw If any of \a meshes is NULL.
7944 * \throw If the coordinates array is not set in any of \a meshes.
7945 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7946 * \throw If \a meshes are of different space dimension.
7948 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
7950 std::size_t sz=meshes.size();
7953 std::vector< const DataArrayDouble * > coords(meshes.size());
7954 std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7955 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7959 (*it)->checkConnectivityFullyDefined();
7960 const DataArrayDouble *coo=(*it)->getCoords();
7965 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7966 oss << " has no coordinate array defined !";
7967 throw INTERP_KERNEL::Exception(oss.str().c_str());
7972 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7973 oss << " is null !";
7974 throw INTERP_KERNEL::Exception(oss.str().c_str());
7977 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7978 std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7979 int offset=(*it)->getNumberOfNodes();
7980 (*it++)->setCoords(res);
7981 for(;it!=meshes.end();it++)
7983 int oldNumberOfNodes=(*it)->getNumberOfNodes();
7984 (*it)->setCoords(res);
7985 (*it)->shiftNodeNumbersInConn(offset);
7986 offset+=oldNumberOfNodes;
7991 * Merges nodes coincident with a given precision within all given meshes that share
7992 * the nodal connectivity array. The given meshes **can be of different** mesh
7993 * dimension. This method is particulary useful in MEDLoader context to build a \ref
7994 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7995 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7996 * \param [in,out] meshes - a vector of meshes to update.
7997 * \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7998 * \throw If any of \a meshes is NULL.
7999 * \throw If the \a meshes do not share the same node coordinates array.
8000 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8002 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
8006 std::set<const DataArrayDouble *> s;
8007 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8010 s.insert((*it)->getCoords());
8013 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 !";
8014 throw INTERP_KERNEL::Exception(oss.str().c_str());
8019 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 !";
8020 throw INTERP_KERNEL::Exception(oss.str().c_str());
8022 const DataArrayDouble *coo=*(s.begin());
8026 DataArrayInt *comm,*commI;
8027 coo->findCommonTuples(eps,-1,comm,commI);
8028 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
8029 int oldNbOfNodes=coo->getNumberOfTuples();
8031 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
8032 if(oldNbOfNodes==newNbOfNodes)
8034 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
8035 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8037 (*it)->renumberNodesInConn(o2n->getConstPointer());
8038 (*it)->setCoords(newCoords);
8043 * 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.
8044 * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
8045 * \param isQuad specifies the policy of connectivity.
8046 * @ret in/out parameter in which the result will be append
8048 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
8050 INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
8051 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
8052 ret.push_back(cm.getExtrudedType());
8053 int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
8056 case INTERP_KERNEL::NORM_POINT1:
8058 ret.push_back(connBg[1]);
8059 ret.push_back(connBg[1]+nbOfNodesPerLev);
8062 case INTERP_KERNEL::NORM_SEG2:
8064 int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
8065 ret.insert(ret.end(),conn,conn+4);
8068 case INTERP_KERNEL::NORM_SEG3:
8070 int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8071 ret.insert(ret.end(),conn,conn+8);
8074 case INTERP_KERNEL::NORM_QUAD4:
8076 int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8077 ret.insert(ret.end(),conn,conn+8);
8080 case INTERP_KERNEL::NORM_TRI3:
8082 int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8083 ret.insert(ret.end(),conn,conn+6);
8086 case INTERP_KERNEL::NORM_TRI6:
8088 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,
8089 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8090 ret.insert(ret.end(),conn,conn+15);
8093 case INTERP_KERNEL::NORM_QUAD8:
8096 connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8097 connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8098 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8100 ret.insert(ret.end(),conn,conn+20);
8103 case INTERP_KERNEL::NORM_POLYGON:
8105 std::back_insert_iterator< std::vector<int> > ii(ret);
8106 std::copy(connBg+1,connEnd,ii);
8108 std::reverse_iterator<const int *> rConnBg(connEnd);
8109 std::reverse_iterator<const int *> rConnEnd(connBg+1);
8110 std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8111 std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8112 for(std::size_t i=0;i<nbOfRadFaces;i++)
8115 int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8116 std::copy(conn,conn+4,ii);
8121 throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8126 * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8128 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8131 double v[3]={0.,0.,0.};
8132 std::size_t sz=std::distance(begin,end);
8137 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];
8138 v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8139 v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8141 double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8143 // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8144 // SEG3 forming a circle):
8145 if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8147 v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8148 for(std::size_t j=0;j<sz;j++)
8150 if (j%2) // current point i is quadratic, next point i+1 is standard
8153 ip1 = (j+1)%sz; // ip1 = "i+1"
8155 else // current point i is standard, next point i+1 is quadratic
8160 v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8161 v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8162 v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8164 ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8170 * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8172 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8174 std::vector<std::pair<int,int> > edges;
8175 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8176 const int *bgFace=begin;
8177 for(std::size_t i=0;i<nbOfFaces;i++)
8179 const int *endFace=std::find(bgFace+1,end,-1);
8180 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8181 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8183 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8184 if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8186 edges.push_back(p1);
8190 return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8194 * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8196 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8198 double vec0[3],vec1[3];
8199 std::size_t sz=std::distance(begin,end);
8201 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8202 int nbOfNodes=(int)sz/2;
8203 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8204 const double *pt0=coords+3*begin[0];
8205 const double *pt1=coords+3*begin[nbOfNodes];
8206 vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8207 return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8210 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8212 std::size_t sz=std::distance(begin,end);
8213 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8214 std::size_t nbOfNodes(sz/2);
8215 std::copy(begin,end,(int *)tmp);
8216 for(std::size_t j=1;j<nbOfNodes;j++)
8218 begin[j]=tmp[nbOfNodes-j];
8219 begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8223 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8225 std::size_t sz=std::distance(begin,end);
8227 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8228 double vec0[3],vec1[3];
8229 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8230 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];
8231 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;
8234 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8236 std::size_t sz=std::distance(begin,end);
8238 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8240 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8241 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8242 return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8246 * 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 )
8247 * 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
8250 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8251 * \param [in] coords the coordinates with nb of components exactly equal to 3
8252 * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8253 * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8254 * \param [out] res the result is put at the end of the vector without any alteration of the data.
8256 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8258 int nbFaces=std::count(begin+1,end,-1)+1;
8259 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8260 double *vPtr=v->getPointer();
8261 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8262 double *pPtr=p->getPointer();
8263 const int *stFaceConn=begin+1;
8264 for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8266 const int *endFaceConn=std::find(stFaceConn,end,-1);
8267 ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8268 stFaceConn=endFaceConn+1;
8270 pPtr=p->getPointer(); vPtr=v->getPointer();
8271 DataArrayInt *comm1=0,*commI1=0;
8272 v->findCommonTuples(eps,-1,comm1,commI1);
8273 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8274 const int *comm1Ptr=comm1->getConstPointer();
8275 const int *commI1Ptr=commI1->getConstPointer();
8276 int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8277 res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8279 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8280 mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8281 mm->finishInsertingCells();
8283 for(int i=0;i<nbOfGrps1;i++)
8285 int vecId=comm1Ptr[commI1Ptr[i]];
8286 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8287 DataArrayInt *comm2=0,*commI2=0;
8288 tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8289 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8290 const int *comm2Ptr=comm2->getConstPointer();
8291 const int *commI2Ptr=commI2->getConstPointer();
8292 int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8293 for(int j=0;j<nbOfGrps2;j++)
8295 if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8297 res->insertAtTheEnd(begin,end);
8298 res->pushBackSilent(-1);
8302 int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8303 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8304 ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8305 DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8306 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8307 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8308 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8309 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8310 const int *idsNodePtr=idsNode->getConstPointer();
8311 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];
8312 double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8313 double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8314 if(std::abs(norm)>eps)
8316 double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8317 mm3->rotate(center,vec,angle);
8319 mm3->changeSpaceDimension(2);
8320 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8321 const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8322 const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8323 int nbOfCells=mm4->getNumberOfCells();
8324 for(int k=0;k<nbOfCells;k++)
8327 for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8328 res->pushBackSilent(idsNodePtr[*work]);
8329 res->pushBackSilent(-1);
8334 res->popBackSilent();
8338 * 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
8339 * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8341 * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8342 * \param [in] coords coordinates expected to have 3 components.
8343 * \param [in] begin start of the nodal connectivity of the face.
8344 * \param [in] end end of the nodal connectivity (excluded) of the face.
8345 * \param [out] v the normalized vector of size 3
8346 * \param [out] p the pos of plane
8348 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8350 std::size_t nbPoints=std::distance(begin,end);
8352 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8353 double vec[3]={0.,0.,0.};
8355 bool refFound=false;
8356 for(;j<nbPoints-1 && !refFound;j++)
8358 vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8359 vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8360 vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8361 double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8365 vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8368 for(std::size_t i=j;i<nbPoints-1;i++)
8371 curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8372 curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8373 curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8374 double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8377 curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8378 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];
8379 norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8382 v[0]/=norm; v[1]/=norm; v[2]/=norm;
8383 *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8387 throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8391 * This method tries to obtain a well oriented polyhedron.
8392 * If the algorithm fails, an exception will be thrown.
8394 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8396 std::list< std::pair<int,int> > edgesOK,edgesFinished;
8397 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8398 std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8400 int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8401 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8402 for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8404 while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8407 std::size_t smthChanged=0;
8408 for(std::size_t i=0;i<nbOfFaces;i++)
8410 endFace=std::find(bgFace+1,end,-1);
8411 nbOfEdgesInFace=std::distance(bgFace,endFace);
8415 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8417 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8418 std::pair<int,int> p2(p1.second,p1.first);
8419 bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8420 bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8421 if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8426 std::reverse(bgFace+1,endFace);
8427 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8429 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8430 std::pair<int,int> p2(p1.second,p1.first);
8431 if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8432 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8433 if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8434 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8435 std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8436 if(it!=edgesOK.end())
8439 edgesFinished.push_back(p1);
8442 edgesOK.push_back(p1);
8449 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8451 if(!edgesOK.empty())
8452 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8453 if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8454 {//not lucky ! The first face was not correctly oriented : reorient all faces...
8456 for(std::size_t i=0;i<nbOfFaces;i++)
8458 endFace=std::find(bgFace+1,end,-1);
8459 std::reverse(bgFace+1,endFace);
8465 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8467 int nbOfNodesExpected(skin->getNumberOfNodes());
8468 const int *n2oPtr(n2o->getConstPointer());
8469 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8470 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8471 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8472 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8473 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8474 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8475 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_POLYGON;
8476 if(nbOfNodesExpected<1)
8478 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8479 *work++=n2oPtr[prevNode];
8480 for(int i=1;i<nbOfNodesExpected;i++)
8482 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8484 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8485 conn.erase(prevNode);
8488 int curNode(*(conn.begin()));
8489 *work++=n2oPtr[curNode];
8490 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8491 shar.erase(prevCell);
8494 prevCell=*(shar.begin());
8498 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8501 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8504 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8509 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8511 int nbOfNodesExpected(skin->getNumberOfNodes());
8512 int nbOfTurn(nbOfNodesExpected/2);
8513 const int *n2oPtr(n2o->getConstPointer());
8514 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8515 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8516 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8517 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8518 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8519 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8520 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_QPOLYG;
8521 if(nbOfNodesExpected<1)
8523 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8524 *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8525 for(int i=1;i<nbOfTurn;i++)
8527 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8529 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8530 conn.erase(prevNode);
8533 int curNode(*(conn.begin()));
8534 *work=n2oPtr[curNode];
8535 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8536 shar.erase(prevCell);
8539 int curCell(*(shar.begin()));
8540 work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8546 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8549 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8552 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8558 * This method makes the assumption spacedimension == meshdimension == 2.
8559 * This method works only for linear cells.
8561 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8563 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8565 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8566 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8567 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8568 int oldNbOfNodes(skin->getNumberOfNodes());
8569 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8570 int nbOfNodesExpected(skin->getNumberOfNodes());
8571 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8572 int nbCells(skin->getNumberOfCells());
8573 if(nbCells==nbOfNodesExpected)
8574 return buildUnionOf2DMeshLinear(skin,n2o);
8575 else if(2*nbCells==nbOfNodesExpected)
8576 return buildUnionOf2DMeshQuadratic(skin,n2o);
8578 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8582 * This method makes the assumption spacedimension == meshdimension == 3.
8583 * This method works only for linear cells.
8585 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8587 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8589 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8590 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8591 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8592 const int *conn=m->getNodalConnectivity()->getConstPointer();
8593 const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8594 int nbOfCells=m->getNumberOfCells();
8595 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8596 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED;
8599 work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8600 for(int i=1;i<nbOfCells;i++)
8603 work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8609 * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8610 * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8612 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8616 for(int i=0;i<nbOfNodesInCell;i++)
8617 w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8618 else if(spaceDim==2)
8620 for(int i=0;i<nbOfNodesInCell;i++)
8622 w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8627 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8630 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8632 int nbOfCells=getNumberOfCells();
8634 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8635 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};
8636 ofs << " <" << getVTKDataSetType() << ">\n";
8637 ofs << " <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8638 ofs << " <PointData>\n" << pointData << std::endl;
8639 ofs << " </PointData>\n";
8640 ofs << " <CellData>\n" << cellData << std::endl;
8641 ofs << " </CellData>\n";
8642 ofs << " <Points>\n";
8643 if(getSpaceDimension()==3)
8644 _coords->writeVTK(ofs,8,"Points",byteData);
8647 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8648 coo->writeVTK(ofs,8,"Points",byteData);
8650 ofs << " </Points>\n";
8651 ofs << " <Cells>\n";
8652 const int *cPtr=_nodal_connec->getConstPointer();
8653 const int *cIPtr=_nodal_connec_index->getConstPointer();
8654 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8655 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8656 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8657 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8658 int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8659 int szFaceOffsets=0,szConn=0;
8660 for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8663 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8666 *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8667 w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8671 int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8672 *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8673 std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8674 *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8675 w4=std::copy(c.begin(),c.end(),w4);
8678 types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8679 types->writeVTK(ofs,8,"UInt8","types",byteData);
8680 offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8681 if(szFaceOffsets!=0)
8682 {//presence of Polyhedra
8683 connectivity->reAlloc(szConn);
8684 faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8685 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8686 w1=faces->getPointer();
8687 for(int i=0;i<nbOfCells;i++)
8688 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8690 int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8692 const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8693 for(int j=0;j<nbFaces;j++)
8695 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8696 *w1++=(int)std::distance(w6,w5);
8697 w1=std::copy(w6,w5,w1);
8701 faces->writeVTK(ofs,8,"Int32","faces",byteData);
8703 connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8704 ofs << " </Cells>\n";
8705 ofs << " </Piece>\n";
8706 ofs << " </" << getVTKDataSetType() << ">\n";
8709 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8711 stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8713 { stream << " Not set !"; return ; }
8714 stream << " Mesh dimension : " << _mesh_dim << ".";
8718 { stream << " No coordinates set !"; return ; }
8719 if(!_coords->isAllocated())
8720 { stream << " Coordinates set but not allocated !"; return ; }
8721 stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8722 stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8723 if(!_nodal_connec_index)
8724 { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8725 if(!_nodal_connec_index->isAllocated())
8726 { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8727 int lgth=_nodal_connec_index->getNumberOfTuples();
8728 int cpt=_nodal_connec_index->getNumberOfComponents();
8729 if(cpt!=1 || lgth<1)
8731 stream << std::endl << "Number of cells : " << lgth-1 << ".";
8734 std::string MEDCouplingUMesh::getVTKDataSetType() const
8736 return std::string("UnstructuredGrid");
8739 std::string MEDCouplingUMesh::getVTKFileExtension() const
8741 return std::string("vtu");
8745 * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8746 * returns a result mesh constituted by polygons.
8747 * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8748 * all nodes from m2.
8749 * The meshes should be in 2D space. In
8750 * addition, returns two arrays mapping cells of the result mesh to cells of the input
8752 * \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
8753 * 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)
8754 * \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
8755 * 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)
8756 * \param [in] eps - precision used to detect coincident mesh entities.
8757 * \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8758 * cell an id of the cell of \a m1 it comes from. The caller is to delete
8759 * this array using decrRef() as it is no more needed.
8760 * \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8761 * cell an id of the cell of \a m2 it comes from. -1 value means that a
8762 * result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8763 * any cell of \a m2. The caller is to delete this array using decrRef() as
8764 * it is no more needed.
8765 * \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8766 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8767 * is no more needed.
8768 * \throw If the coordinates array is not set in any of the meshes.
8769 * \throw If the nodal connectivity of cells is not defined in any of the meshes.
8770 * \throw If any of the meshes is not a 2D mesh in 2D space.
8772 * \sa conformize2D, mergeNodes
8774 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8775 double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8778 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
8779 m1->checkFullyDefined();
8780 m2->checkFullyDefined();
8781 if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8782 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!");
8784 // Step 1: compute all edge intersections (new nodes)
8785 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8786 MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
8787 DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8788 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
8789 IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
8790 m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8791 addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
8792 revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8793 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8794 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8796 // Step 2: re-order newly created nodes according to the ordering found in m2
8797 std::vector< std::vector<int> > intersectEdge2;
8798 BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8799 subDiv2.clear(); dd5=0; dd6=0;
8802 std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8803 std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8804 BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8805 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8807 // Step 4: Prepare final result:
8808 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
8809 addCooDa->alloc((int)(addCoo.size())/2,2);
8810 std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8811 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
8812 addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8813 std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8814 std::vector<const DataArrayDouble *> coordss(4);
8815 coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8816 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
8817 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
8818 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8819 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8820 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8821 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8822 ret->setConnectivity(conn,connI,true);
8823 ret->setCoords(coo);
8824 cellNb1=c1.retn(); cellNb2=c2.retn();
8830 bool IsColinearOfACellOf(const std::vector< std::vector<int> >& intersectEdge1, const std::vector<int>& candidates, int start, int stop, int& retVal)
8832 if(candidates.empty())
8834 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
8836 const std::vector<int>& pool(intersectEdge1[*it]);
8837 int tmp[2]; tmp[0]=start; tmp[1]=stop;
8838 if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
8843 tmp[0]=stop; tmp[1]=start;
8844 if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
8853 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,
8854 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInRetColinear, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInMesh1DForIdsInRetColinear)
8856 idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1);
8857 idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1);
8858 int nCells(mesh1D->getNumberOfCells());
8859 if(nCells!=(int)intersectEdge2.size())
8860 throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
8861 const DataArrayDouble *coo2(mesh1D->getCoords());
8862 const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
8863 const double *coo2Ptr(coo2->begin());
8864 int offset1(coords1->getNumberOfTuples());
8865 int offset2(offset1+coo2->getNumberOfTuples());
8866 int offset3(offset2+addCoo.size()/2);
8867 std::vector<double> addCooQuad;
8868 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
8869 int tmp[4],cicnt(0),kk(0);
8870 for(int i=0;i<nCells;i++)
8872 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
8873 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
8874 const std::vector<int>& subEdges(intersectEdge2[i]);
8875 int nbSubEdge(subEdges.size()/2);
8876 for(int j=0;j<nbSubEdge;j++,kk++)
8878 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));
8879 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
8880 INTERP_KERNEL::Edge *e2Ptr(e2);
8881 std::map<int,int>::const_iterator itm;
8882 if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
8884 tmp[0]=INTERP_KERNEL::NORM_SEG3;
8885 itm=mergedNodes.find(subEdges[2*j]);
8886 tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
8887 itm=mergedNodes.find(subEdges[2*j+1]);
8888 tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
8889 tmp[3]=offset3+(int)addCooQuad.size()/2;
8891 e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2);
8893 cOut->insertAtTheEnd(tmp,tmp+4);
8894 ciOut->pushBackSilent(cicnt);
8898 tmp[0]=INTERP_KERNEL::NORM_SEG2;
8899 itm=mergedNodes.find(subEdges[2*j]);
8900 tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
8901 itm=mergedNodes.find(subEdges[2*j+1]);
8902 tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
8904 cOut->insertAtTheEnd(tmp,tmp+3);
8905 ciOut->pushBackSilent(cicnt);
8908 if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00))
8910 idsInRetColinear->pushBackSilent(kk);
8911 idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00);
8916 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
8917 ret->setConnectivity(cOut,ciOut,true);
8918 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr3(DataArrayDouble::New());
8919 arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
8920 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
8921 std::vector<const DataArrayDouble *> coordss(4);
8922 coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
8923 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
8924 ret->setCoords(arr);
8928 MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
8930 std::vector<int> allEdges;
8931 for(const int *it2(descBg);it2!=descEnd;it2++)
8933 const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
8935 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
8937 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
8939 std::size_t nb(allEdges.size());
8941 throw INTERP_KERNEL::Exception("BuildRefined2DCell : internal error 1 !");
8942 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
8943 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
8944 ret->setCoords(coords);
8945 ret->allocateCells(1);
8946 std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
8947 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
8948 connOut[kk]=allEdges[2*kk];
8949 ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]);
8953 void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector<int>& conn, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edges)
8956 for(std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >::const_iterator it=edges.begin();it!=edges.end();it++)
8958 const INTERP_KERNEL::Edge *ee(*it);
8959 if(dynamic_cast<const INTERP_KERNEL::EdgeArcCircle *>(ee))
8963 mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]);
8966 const double *coo(mesh2D->getCoords()->begin());
8967 std::size_t sz(conn.size());
8968 std::vector<double> addCoo;
8969 std::vector<int> conn2(conn);
8970 int offset(mesh2D->getNumberOfNodes());
8971 for(std::size_t i=0;i<sz;i++)
8974 edges[(i+1)%sz]->getMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);
8975 addCoo.insert(addCoo.end(),tmp,tmp+2);
8976 conn2.push_back(offset+(int)i);
8978 mesh2D->getCoords()->rearrange(1);
8979 mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size());
8980 mesh2D->getCoords()->rearrange(2);
8981 mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]);
8986 * \b WARNING edges in out1 coming from \a splitMesh1D are \b NOT oriented because only used for equation of curve.
8988 void BuildMesh2DCutInternal2(const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& edge1Bis, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edge1BisPtr,
8989 std::vector< std::vector<int> >& out0, std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& out1)
8991 std::size_t nb(edge1Bis.size()/2);
8992 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
8993 int iEnd(splitMesh1D->getNumberOfCells());
8995 throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal2 : internal error ! input 1D mesh must have at least one cell !");
8997 const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
8998 for(ii=0;ii<nb && edge1Bis[2*ii]!=cSplitPtr[ciSplitPtr[0]+1];ii++);
8999 for(jj=ii;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd-1]+2];jj++);
9002 {//the edges splitMesh1D[iStart:iEnd] does not fully cut the current 2D cell -> single output cell
9003 out0.resize(1); out1.resize(1);
9004 std::vector<int>& connOut(out0[0]);
9005 connOut.resize(nbOfEdgesOf2DCellSplit);
9006 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr(out1[0]);
9007 edgesPtr.resize(nbOfEdgesOf2DCellSplit);
9008 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9010 connOut[kk]=edge1Bis[2*kk];
9011 edgesPtr[kk]=edge1BisPtr[2*kk];
9016 // [i,iEnd[ contains the
9017 out0.resize(2); out1.resize(2);
9018 std::vector<int>& connOutLeft(out0[0]);
9019 std::vector<int>& connOutRight(out0[1]);//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1]
9020 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eleft(out1[0]);
9021 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eright(out1[1]);
9022 for(std::size_t k=ii;k<jj+1;k++)
9023 { connOutLeft.push_back(edge1Bis[2*k+1]); eleft.push_back(edge1BisPtr[2*k+1]); }
9024 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > ees(iEnd);
9025 for(int ik=iEnd-1;ik>=0;ik--)
9027 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9028 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9031 for(int ik=iEnd-1;ik>=0;ik--)
9032 connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]);
9033 for(std::size_t k=jj+1;k<nbOfEdgesOf2DCellSplit+ii;k++)
9034 { connOutRight.push_back(edge1Bis[2*k+1]); eright.push_back(edge1BisPtr[2*k+1]); }
9035 eleft.insert(eleft.end(),ees.begin(),ees.end());
9036 for(int ik=0;ik<iEnd;ik++)
9037 connOutRight.push_back(cSplitPtr[ciSplitPtr[ik]+2]);
9038 eright.insert(eright.end(),ees.rbegin(),ees.rend());
9050 CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9052 std::vector<int> _edges;
9053 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > _edges_ptr;
9056 CellInfo::CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr)
9058 std::size_t nbe(edges.size());
9059 std::vector<int> edges2(2*nbe); std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edgesPtr2(2*nbe);
9060 for(std::size_t i=0;i<nbe;i++)
9062 edges2[2*i]=edges[i]; edges2[2*i+1]=edges[(i+1)%nbe];
9063 edgesPtr2[2*i]=edgesPtr[i]; edgesPtr2[2*i+1]=edgesPtr[i];
9065 _edges.resize(4*nbe); _edges_ptr.resize(4*nbe);
9066 std::copy(edges2.begin(),edges2.end(),_edges.begin()); std::copy(edges2.begin(),edges2.end(),_edges.begin()+2*nbe);
9067 std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()); std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()+2*nbe);
9073 EdgeInfo(int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh):_istart(istart),_iend(iend),_mesh(mesh),_left(-7),_right(-7) { }
9074 EdgeInfo(int istart, int iend, int pos, const MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge>& edge):_istart(istart),_iend(iend),_edge(edge),_left(pos),_right(pos+1) { }
9075 bool isInMyRange(int pos) const { return pos>=_istart && pos<_iend; }
9076 void somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9077 void feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const;
9081 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _mesh;
9082 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> _edge;
9087 void EdgeInfo::somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9089 const MEDCouplingUMesh *mesh(_mesh);
9095 { _left++; _right++; return ; }
9098 bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9099 if((isLeft && isRight) || (!isLeft && !isRight))
9100 throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 1 !");
9111 bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9112 if((isLeft && isRight) || (!isLeft && !isRight))
9113 throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 2 !");
9128 void EdgeInfo::feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const
9130 const MEDCouplingUMesh *mesh(_mesh);
9133 neighbors[0]=offset+_left; neighbors[1]=offset+_right;
9136 {// not fully splitting cell case
9137 if(mesh2D->getNumberOfCells()==1)
9138 {//little optimization. 1 cell no need to find in which cell mesh is !
9139 neighbors[0]=offset; neighbors[1]=offset;
9144 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9145 int cellId(mesh2D->getCellContainingPoint(barys->begin(),eps));
9147 throw INTERP_KERNEL::Exception("EdgeInfo::feedEdgeInfoAt : internal error !");
9148 neighbors[0]=offset+cellId; neighbors[1]=offset+cellId;
9153 class VectorOfCellInfo
9156 VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9157 std::size_t size() const { return _pool.size(); }
9158 int getPositionOf(double eps, const MEDCouplingUMesh *mesh) const;
9159 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);
9160 const std::vector<int>& getConnOf(int pos) const { return get(pos)._edges; }
9161 const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& getEdgePtrOf(int pos) const { return get(pos)._edges_ptr; }
9162 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> getZeMesh() const { return _ze_mesh; }
9163 void feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const;
9165 int getZePosOfEdgeGivenItsGlobalId(int pos) const;
9166 void updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9167 const CellInfo& get(int pos) const;
9168 CellInfo& get(int pos);
9170 std::vector<CellInfo> _pool;
9171 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _ze_mesh;
9172 std::vector<EdgeInfo> _edge_info;
9175 VectorOfCellInfo::VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr):_pool(1)
9177 _pool[0]._edges=edges;
9178 _pool[0]._edges_ptr=edgesPtr;
9181 int VectorOfCellInfo::getPositionOf(double eps, const MEDCouplingUMesh *mesh) const
9184 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : empty !");
9187 const MEDCouplingUMesh *zeMesh(_ze_mesh);
9189 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : null aggregated mesh !");
9190 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9191 return zeMesh->getCellContainingPoint(barys->begin(),eps);
9194 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)
9196 get(pos);//to check pos
9197 bool isFast(pos==0 && _pool.size()==1);
9198 std::size_t sz(edges.size());
9199 // dealing with edges
9201 _edge_info.push_back(EdgeInfo(istart,iend,mesh1DInCase));
9203 _edge_info.push_back(EdgeInfo(istart,iend,pos,edgePtrs[0].back()));
9205 std::vector<CellInfo> pool(_pool.size()-1+sz);
9206 for(int i=0;i<pos;i++)
9208 for(std::size_t j=0;j<sz;j++)
9209 pool[pos+j]=CellInfo(edges[j],edgePtrs[j]);
9210 for(int i=pos+1;i<(int)_pool.size();i++)
9211 pool[pos+sz-1]=_pool[i];
9215 updateEdgeInfo(pos,edgePtrs[0],edgePtrs[1]);
9223 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > ms;
9226 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(0,pos,true)));
9230 if(pos<_ze_mesh->getNumberOfCells()-1)
9232 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(pos+1,_ze_mesh->getNumberOfCells(),true)));
9235 std::vector< const MEDCouplingUMesh *> ms2(ms.size());
9236 for(std::size_t j=0;j<ms2.size();j++)
9238 _ze_mesh=MEDCouplingUMesh::MergeUMeshesOnSameCoords(ms2);
9241 void VectorOfCellInfo::feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const
9243 _edge_info[getZePosOfEdgeGivenItsGlobalId(pos)].feedEdgeInfoAt(eps,_ze_mesh,offset,neighbors);
9246 int VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId(int pos) const
9249 throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id ! Must be >=0 !");
9251 for(std::vector<EdgeInfo>::const_iterator it=_edge_info.begin();it!=_edge_info.end();it++,ret++)
9253 if((*it).isInMyRange(pos))
9256 throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id !");
9259 void VectorOfCellInfo::updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9261 get(pos);//to check;
9262 if(_edge_info.empty())
9264 std::size_t sz(_edge_info.size()-1);
9265 for(std::size_t i=0;i<sz;i++)
9266 _edge_info[i].somethingHappendAt(pos,newLeft,newRight);
9269 const CellInfo& VectorOfCellInfo::get(int pos) const
9271 if(pos<0 || pos>=(int)_pool.size())
9272 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get const : invalid pos !");
9276 CellInfo& VectorOfCellInfo::get(int pos)
9278 if(pos<0 || pos>=(int)_pool.size())
9279 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get : invalid pos !");
9283 MEDCouplingUMesh *BuildMesh2DCutInternal(double eps, const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& allEdges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& allEdgesPtr, int offset,
9284 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9286 int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells());
9287 if(nbCellsInSplitMesh1D==0)
9288 throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal : internal error ! input 1D mesh must have at least one cell !");
9289 const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9290 std::size_t nb(allEdges.size()),jj;
9292 throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !");
9293 std::vector<int> edge1Bis(nb*2);
9294 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edge1BisPtr(nb*2);
9295 std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin());
9296 std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb);
9297 std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin());
9298 std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb);
9300 idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(nbCellsInSplitMesh1D*2); idsLeftRight->fillWithValue(-2); idsLeftRight->rearrange(2);
9301 int *idsLeftRightPtr(idsLeftRight->getPointer());
9302 VectorOfCellInfo pool(edge1Bis,edge1BisPtr);
9303 for(int iStart=0;iStart<nbCellsInSplitMesh1D;)
9304 {// split [0:nbCellsInSplitMesh1D) in contiguous parts [iStart:iEnd)
9306 for(;iEnd<nbCellsInSplitMesh1D;)
9308 for(jj=0;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd]+2];jj++);
9314 if(iEnd<nbCellsInSplitMesh1D)
9317 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfSplitMesh1D(static_cast<MEDCouplingUMesh *>(splitMesh1D->buildPartOfMySelf2(iStart,iEnd,1,true)));
9318 int pos(pool.getPositionOf(eps,partOfSplitMesh1D));
9320 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>retTmp(MEDCouplingUMesh::New("",2));
9321 retTmp->setCoords(splitMesh1D->getCoords());
9322 retTmp->allocateCells();
9324 std::vector< std::vector<int> > out0;
9325 std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > > out1;
9327 BuildMesh2DCutInternal2(partOfSplitMesh1D,pool.getConnOf(pos),pool.getEdgePtrOf(pos),out0,out1);
9328 for(std::size_t cnt=0;cnt<out0.size();cnt++)
9329 AddCellInMesh2D(retTmp,out0[cnt],out1[cnt]);
9330 pool.setMeshAt(pos,retTmp,iStart,iEnd,partOfSplitMesh1D,out0,out1);
9334 for(int mm=0;mm<nbCellsInSplitMesh1D;mm++)
9335 pool.feedEdgeInfoAt(eps,mm,offset,idsLeftRightPtr+2*mm);
9336 return pool.getZeMesh().retn();
9339 MEDCouplingUMesh *BuildMesh2DCutFrom(double eps, int cellIdInMesh2D, const MEDCouplingUMesh *mesh2DDesc, const MEDCouplingUMesh *splitMesh1D,
9340 const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1, int offset,
9341 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9343 const int *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin());
9345 std::vector<int> allEdges;
9346 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > allEdgesPtr;
9347 for(const int *it(descBg);it!=descEnd;it++)
9349 int edgeId(std::abs(*it)-1);
9350 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9351 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m));
9352 const std::vector<int>& edge1(intersectEdge1[edgeId]);
9354 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9356 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9357 std::size_t sz(edge1.size());
9358 for(std::size_t cnt=0;cnt<sz;cnt++)
9359 allEdgesPtr.push_back(ee);
9362 return BuildMesh2DCutInternal(eps,splitMesh1D,allEdges,allEdgesPtr,offset,idsLeftRight);
9368 * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
9369 * 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
9370 * and finaly, in case of quadratic polygon the centers of edges new nodes.
9371 * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
9373 * \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
9374 * 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)
9375 * \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
9376 * you can invoke orderConsecutiveCells1D on \a mesh1D.
9377 * \param [in] eps - precision used to perform intersections and localization operations.
9378 * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
9379 * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
9380 * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
9381 * 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.
9382 * \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
9383 * and the cell in \a splitMesh2D on the right for the 2nt component. -1 means no cell.
9384 * 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.
9386 * \sa Intersect2DMeshes, orderConsecutiveCells1D, conformize2D, mergeNodes
9388 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
9390 if(!mesh2D || !mesh1D)
9391 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
9392 mesh2D->checkFullyDefined();
9393 mesh1D->checkFullyDefined();
9394 const std::vector<std::string>& compNames(mesh2D->getCoords()->getInfoOnComponents());
9395 if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
9396 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
9397 // Step 1: compute all edge intersections (new nodes)
9398 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9399 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
9400 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9401 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9403 // Build desc connectivity
9404 DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
9405 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9406 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
9407 std::map<int,int> mergedNodes;
9408 Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes);
9409 // use mergeNodes to fix intersectEdge1
9410 for(std::vector< std::vector<int> >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++)
9412 std::size_t n((*it0).size()/2);
9413 int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]);
9414 std::map<int,int>::const_iterator it1;
9415 it1=mergedNodes.find(eltStart);
9416 if(it1!=mergedNodes.end())
9417 (*it0)[0]=(*it1).second;
9418 it1=mergedNodes.find(eltEnd);
9419 if(it1!=mergedNodes.end())
9420 (*it0)[2*n-1]=(*it1).second;
9423 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9424 addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9425 // Step 2: re-order newly created nodes according to the ordering found in m2
9426 std::vector< std::vector<int> > intersectEdge2;
9427 BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
9429 // Step 3: compute splitMesh1D
9430 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear;
9431 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2(DataArrayInt::New()); ret2->alloc(0,1);
9432 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1,
9433 idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear));
9434 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(-1); ret3->rearrange(2);
9435 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells()));
9436 // deal with cells in mesh2D that are not cut but only some of their edges are
9437 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCpy());
9438 idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1);
9439 idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique();
9440 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
9441 if(!idsInDesc2DToBeRefined->empty())
9443 DataArrayInt *out0(0),*outi0(0);
9444 MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
9445 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> outi0s(outi0);
9447 out0s=out0s->buildUnique();
9451 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1NonCol(static_cast<MEDCouplingUMesh *>(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end())));
9452 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> baryRet1(ret1NonCol->getBarycenterAndOwner());
9453 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elts,eltsIndex;
9454 mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
9455 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex2(eltsIndex->deltaShiftIndex());
9456 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex3(eltsIndex2->getIdsEqual(1));
9457 if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells())
9458 throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !");
9459 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToBeModified(elts->buildUnique());
9460 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells()));
9461 if((DataArrayInt *)out0s)
9462 untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one
9463 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > outMesh2DSplit;
9464 // OK all is ready to insert in ret2 mesh
9465 if(!untouchedCells->empty())
9466 {// the most easy part, cells in mesh2D not impacted at all
9467 outMesh2DSplit.push_back(static_cast<MEDCouplingUMesh *>(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end())));
9468 outMesh2DSplit.back()->setCoords(ret1->getCoords());
9469 ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end());
9471 if((DataArrayInt *)out0s)
9472 {// here dealing with cells in out0s but not in cellsToBeModified
9473 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fewModifiedCells(out0s->buildSubstraction(cellsToBeModified));
9474 const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin());
9475 for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++)
9477 outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1));
9479 int offset(ret2->getNumberOfTuples());
9480 ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end());
9481 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1);
9482 partOfRet3->fillWithValue(-1); partOfRet3->rearrange(2);
9483 int kk(0),*ret3ptr(partOfRet3->getPointer());
9484 for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++)
9486 int faceId(std::abs(*it)-1);
9487 for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++)
9489 int tmp(fewModifiedCells->locateValue(*it2));
9492 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9493 ret3ptr[2*kk]=tmp+offset;
9494 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9495 ret3ptr[2*kk+1]=tmp+offset;
9498 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : internal error 1 !");
9501 ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true);
9503 for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++)
9505 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell(elts->getIdsEqual(*it));
9506 idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end());
9507 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end()));
9508 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfMesh1CuttingCur2DCell(static_cast<MEDCouplingUMesh *>(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end())));
9509 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3;
9510 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));
9511 ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true);
9512 outMesh2DSplit.push_back(splitOfOneCell);
9513 for(int i=0;i<splitOfOneCell->getNumberOfCells();i++)
9514 ret2->pushBackSilent(*it);
9517 std::size_t nbOfMeshes(outMesh2DSplit.size());
9518 std::vector<const MEDCouplingUMesh *> tmp(nbOfMeshes);
9519 for(std::size_t i=0;i<nbOfMeshes;i++)
9520 tmp[i]=outMesh2DSplit[i];
9522 ret1->getCoords()->setInfoOnComponents(compNames);
9524 splitMesh1D=ret1.retn();
9525 splitMesh2D=MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp);
9526 cellIdInMesh2D=ret2.retn();
9527 cellIdInMesh1D=ret3.retn();
9531 * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
9532 * (newly created) nodes corresponding to the edge intersections.
9534 * @param[out] cr, crI connectivity of the resulting mesh
9535 * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
9536 * TODO: describe input parameters
9538 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
9539 const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
9540 const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
9541 const std::vector<double>& addCoords,
9542 std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
9544 static const int SPACEDIM=2;
9545 const double *coo1(m1->getCoords()->getConstPointer());
9546 const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer());
9547 int offset1(m1->getNumberOfNodes());
9548 const double *coo2(m2->getCoords()->getConstPointer());
9549 const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer());
9550 int offset2(offset1+m2->getNumberOfNodes());
9551 int offset3(offset2+((int)addCoords.size())/2);
9552 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
9553 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9554 // Here a BBTree on 2D-cells, not on segments:
9555 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
9556 int ncell1(m1->getNumberOfCells());
9558 for(int i=0;i<ncell1;i++)
9560 std::vector<int> candidates2;
9561 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9562 std::map<INTERP_KERNEL::Node *,int> mapp;
9563 std::map<int,INTERP_KERNEL::Node *> mappRev;
9564 INTERP_KERNEL::QuadraticPolygon pol1;
9565 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
9566 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
9567 // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
9568 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
9569 // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
9570 pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
9571 desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
9573 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
9574 std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
9575 INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
9576 for(it1.first();!it1.finished();it1.next())
9577 edges1.insert(it1.current()->getPtr());
9579 std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
9580 std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
9582 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9584 INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
9585 const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
9586 // Complete mapping with elements coming from the current cell it2 in mesh2:
9587 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
9588 // pol2 is the new QP in the final merged result.
9589 pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
9590 pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
9593 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9595 INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
9596 pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
9597 //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
9598 pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9600 // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
9601 // by m2 but that we still want to keep in the final result.
9606 INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9608 catch(INTERP_KERNEL::Exception& e)
9610 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();
9611 throw INTERP_KERNEL::Exception(oss.str().c_str());
9614 for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
9615 (*it).second->decrRef();
9620 * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
9621 * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
9622 * This doesn't modify the mesh.
9623 * The caller is to deal with the resulting DataArrayInt.
9624 * \throw If the coordinate array is not set.
9625 * \throw If the nodal connectivity of the cells is not defined.
9626 * \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
9627 * \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
9629 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
9631 checkFullyDefined();
9632 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
9633 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with (meshdim, spacedim) = (1,2)!");
9635 // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
9636 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
9637 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
9638 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
9639 const int *d(_d->getConstPointer()), *dI(_dI->getConstPointer());
9640 const int *rD(_rD->getConstPointer()), *rDI(_rDI->getConstPointer());
9641 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
9642 const int * dsi(_dsi->getConstPointer());
9643 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dsii = _dsi->getIdsNotInRange(0,3);
9645 if (dsii->getNumberOfTuples())
9646 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
9648 int nc(getNumberOfCells());
9649 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> result(DataArrayInt::New());
9650 result->alloc(nc,1);
9652 // set of edges not used so far
9653 std::set<int> edgeSet;
9654 for (int i=0; i<nc; edgeSet.insert(i), i++);
9658 // while we have points with only one neighbor segments
9661 std::list<int> linePiece;
9662 // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
9663 for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
9665 // Fill the list forward (resp. backward) from the start segment:
9666 int activeSeg = startSeg;
9667 int prevPointId = -20;
9669 while (!edgeSet.empty())
9671 if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
9674 linePiece.push_back(activeSeg);
9676 linePiece.push_front(activeSeg);
9677 edgeSet.erase(activeSeg);
9680 int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
9681 ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
9682 if (dsi[ptId] == 1) // hitting the end of the line
9685 int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
9686 activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
9689 // Done, save final piece into DA:
9690 std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
9691 newIdx += linePiece.size();
9693 // identify next valid start segment (one which is not consumed)
9694 if(!edgeSet.empty())
9695 startSeg = *(edgeSet.begin());
9697 while (!edgeSet.empty());
9698 return result.retn();
9703 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
9705 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> nTmp(n); nTmp->incrRef();
9706 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>::const_iterator it(m.find(nTmp));
9708 throw INTERP_KERNEL::Exception("Internal error in remapping !");
9709 int v((*it).second);
9710 if(v==forbVal0 || v==forbVal1)
9712 if(std::find(isect.begin(),isect.end(),v)==isect.end())
9716 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
9721 bool presenceOfOn(false);
9722 for(int i=0;i<sz;i++)
9724 INTERP_KERNEL::ElementaryEdge *e(c[i]);
9725 if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
9727 IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
9728 IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
9730 return presenceOfOn;
9736 * 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.
9737 * 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.
9738 * 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.
9739 * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to avoid to have a non conform mesh.
9741 * \return int - the number of new nodes created (in most of cases 0).
9743 * \throw If \a this is not coherent.
9744 * \throw If \a this has not spaceDim equal to 2.
9745 * \throw If \a this has not meshDim equal to 2.
9746 * \throw If some subcells needed to be split are orphan.
9747 * \sa MEDCouplingUMesh::conformize2D
9749 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
9751 if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
9752 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
9753 desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
9754 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
9755 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
9756 if(midOpt==0 && midOptI==0)
9758 split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
9761 else if(midOpt!=0 && midOptI!=0)
9762 return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
9764 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
9768 * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
9769 * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
9770 * 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
9771 * 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).
9772 * 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.
9774 * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
9775 * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
9777 * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
9778 * This method expects that all nodes in \a this are not closer than \a eps.
9779 * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
9781 * \param [in] eps the relative error to detect merged edges.
9782 * \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
9783 * that the user is expected to deal with.
9785 * \throw If \a this is not coherent.
9786 * \throw If \a this has not spaceDim equal to 2.
9787 * \throw If \a this has not meshDim equal to 2.
9788 * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
9790 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
9792 static const int SPACEDIM=2;
9794 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
9795 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
9796 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
9797 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
9798 const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
9799 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
9800 const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
9801 int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
9802 std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
9803 std::vector<double> addCoo;
9804 BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
9805 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9806 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9807 for(int i=0;i<nDescCell;i++)
9809 std::vector<int> candidates;
9810 myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
9811 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
9814 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9815 INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
9816 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
9817 INTERP_KERNEL::MergePoints merge;
9818 INTERP_KERNEL::QuadraticPolygon c1,c2;
9819 e1->intersectWith(e2,merge,c1,c2);
9820 e1->decrRef(); e2->decrRef();
9821 if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
9822 overlapEdge[i].push_back(*it);
9823 if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
9824 overlapEdge[*it].push_back(i);
9827 // splitting done. sort intersect point in intersectEdge.
9828 std::vector< std::vector<int> > middle(nDescCell);
9829 int nbOf2DCellsToBeSplit(0);
9830 bool middleNeedsToBeUsed(false);
9831 std::vector<bool> cells2DToTreat(nDescCell,false);
9832 for(int i=0;i<nDescCell;i++)
9834 std::vector<int>& isect(intersectEdge[i]);
9835 int sz((int)isect.size());
9838 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9839 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
9840 e->sortSubNodesAbs(coords,isect);
9845 int idx0(rdi[i]),idx1(rdi[i+1]);
9847 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
9848 if(!cells2DToTreat[rd[idx0]])
9850 cells2DToTreat[rd[idx0]]=true;
9851 nbOf2DCellsToBeSplit++;
9853 // try to reuse at most eventual 'middle' of SEG3
9854 std::vector<int>& mid(middle[i]);
9855 mid.resize(sz+1,-1);
9856 if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
9858 middleNeedsToBeUsed=true;
9859 const std::vector<int>& candidates(overlapEdge[i]);
9860 std::vector<int> trueCandidates;
9861 for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
9862 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
9863 trueCandidates.push_back(*itc);
9864 int stNode(c[ci[i]+1]),endNode(isect[0]);
9865 for(int j=0;j<sz+1;j++)
9867 for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
9869 int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
9870 if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
9871 { mid[j]=*itc; break; }
9874 endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
9879 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
9880 if(nbOf2DCellsToBeSplit==0)
9883 int *retPtr(ret->getPointer());
9884 for(int i=0;i<nCell;i++)
9885 if(cells2DToTreat[i])
9888 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
9889 DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
9890 MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
9891 DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
9892 if(middleNeedsToBeUsed)
9893 { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
9894 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
9895 int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
9896 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.
9897 setPartOfMySelf(ret->begin(),ret->end(),*modif);
9899 bool areNodesMerged; int newNbOfNodes;
9900 if(nbOfNodesCreated!=0)
9901 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
9907 * 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.
9908 * 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).
9909 * 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
9910 * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
9911 * 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
9912 * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
9914 * 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
9915 * using new instance, idem for coordinates.
9917 * 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.
9919 * \return DataArrayInt * - The list of cellIds in \a this that have at least one edge colinearized.
9921 * \throw If \a this is not coherent.
9922 * \throw If \a this has not spaceDim equal to 2.
9923 * \throw If \a this has not meshDim equal to 2.
9925 * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
9927 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
9929 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
9931 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
9932 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
9933 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9934 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9935 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
9936 const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
9937 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
9938 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
9939 const double *coords(_coords->begin());
9940 int *newciptr(newci->getPointer());
9941 for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
9943 if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
9944 ret->pushBackSilent(i);
9945 newciptr[1]=newc->getNumberOfTuples();
9950 if(!appendedCoords->empty())
9952 appendedCoords->rearrange(2);
9953 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
9955 setCoords(newCoords);
9958 setConnectivity(newc,newci,true);
9963 * \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.
9964 * 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.
9965 * And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
9966 * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
9967 * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
9968 * \param [out] addCoo - nodes to be append at the end
9969 * \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.
9971 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
9972 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)
9974 static const int SPACEDIM=2;
9975 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9976 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9977 const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer());
9978 // Build BB tree of all edges in the tool mesh (second mesh)
9979 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
9980 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9981 int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
9982 intersectEdge1.resize(nDescCell1);
9983 colinear2.resize(nDescCell2);
9984 subDiv2.resize(nDescCell2);
9985 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
9987 std::vector<int> candidates1(1);
9988 int offset1(m1Desc->getNumberOfNodes());
9989 int offset2(offset1+m2Desc->getNumberOfNodes());
9990 for(int i=0;i<nDescCell1;i++) // for all edges in the first mesh
9992 std::vector<int> candidates2; // edges of mesh2 candidate for intersection
9993 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9994 if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
9996 std::map<INTERP_KERNEL::Node *,int> map1,map2;
9997 // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
9998 INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
10000 INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
10001 // 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
10002 // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
10003 std::set<INTERP_KERNEL::Node *> nodes;
10004 pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
10005 std::size_t szz(nodes.size());
10006 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
10007 std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
10008 for(std::size_t iii=0;iii<szz;iii++,itt++)
10009 { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
10010 // end of protection
10011 // Performs egde cutting:
10012 pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes);
10017 intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
10022 * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
10023 * It builds the descending connectivity of the two meshes, and then using a binary tree
10024 * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
10025 * Documentation about parameters colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
10027 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
10028 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
10029 MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
10030 std::vector<double>& addCoo,
10031 MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
10033 // Build desc connectivity
10034 desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
10035 desc2=DataArrayInt::New();
10036 descIndx2=DataArrayInt::New();
10037 revDesc2=DataArrayInt::New();
10038 revDescIndx2=DataArrayInt::New();
10039 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
10040 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
10041 m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
10042 m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
10043 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
10044 std::map<int,int> notUsedMap;
10045 Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap);
10046 m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
10047 m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
10051 * This method performs the 2nd step of Partition of 2D mesh.
10052 * This method has 4 inputs :
10053 * - a mesh 'm1' with meshDim==1 and a SpaceDim==2
10054 * - a mesh 'm2' with meshDim==1 and a SpaceDim==2
10055 * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
10056 * 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'
10057 * Nodes end up lying consecutively on a cutted edge.
10058 * \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.
10059 * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
10060 * \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.
10061 * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
10062 * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
10064 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
10065 const std::vector<double>& addCoo,
10066 const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
10068 int offset1=m1->getNumberOfNodes();
10069 int ncell=m2->getNumberOfCells();
10070 const int *c=m2->getNodalConnectivity()->getConstPointer();
10071 const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
10072 const double *coo=m2->getCoords()->getConstPointer();
10073 const double *cooBis=m1->getCoords()->getConstPointer();
10074 int offset2=offset1+m2->getNumberOfNodes();
10075 intersectEdge.resize(ncell);
10076 for(int i=0;i<ncell;i++,cI++)
10078 const std::vector<int>& divs=subDiv[i];
10079 int nnode=cI[1]-cI[0]-1;
10080 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
10081 std::map<INTERP_KERNEL::Node *, int> mapp22;
10082 for(int j=0;j<nnode;j++)
10084 INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
10085 int nnid=c[(*cI)+j+1];
10086 mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
10087 mapp22[nn]=nnid+offset1;
10089 INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
10090 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
10091 ((*it).second.first)->decrRef();
10092 std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
10093 std::map<INTERP_KERNEL::Node *,int> mapp3;
10094 for(std::size_t j=0;j<divs.size();j++)
10097 INTERP_KERNEL::Node *tmp=0;
10099 tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
10100 else if(id<offset2)
10101 tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
10103 tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
10107 e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
10108 for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
10115 * 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).
10116 * 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
10117 * with a plane. The result will be put in 'cut3DSuf' out parameter.
10118 * \param [in] cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
10119 * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
10120 * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
10121 * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
10122 * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
10123 * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
10124 * \param [in] desc is the descending connectivity 3DSurf->3DCurve
10125 * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
10126 * \param [out] cut3DSuf input/output param.
10128 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
10129 const int *nodal3DCurve, const int *nodalIndx3DCurve,
10130 const int *desc, const int *descIndx,
10131 std::vector< std::pair<int,int> >& cut3DSurf)
10133 std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
10134 int nbOf3DSurfCell=(int)cut3DSurf.size();
10135 for(int i=0;i<nbOf3DSurfCell;i++)
10137 std::vector<int> res;
10138 int offset=descIndx[i];
10139 int nbOfSeg=descIndx[i+1]-offset;
10140 for(int j=0;j<nbOfSeg;j++)
10142 int edgeId=desc[offset+j];
10143 int status=cut3DCurve[edgeId];
10147 res.push_back(status);
10150 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
10151 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
10159 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10165 std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
10166 std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
10169 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10173 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
10178 {// case when plane is on a multi colinear edge of a polyhedron
10179 if((int)res.size()==2*nbOfSeg)
10181 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
10184 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
10191 * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
10192 * 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).
10193 * 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
10194 * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
10195 * \param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
10196 * \param desc is the descending connectivity 3D->3DSurf
10197 * \param descIndx is the descending connectivity index 3D->3DSurf
10199 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
10200 const int *desc, const int *descIndx,
10201 DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
10203 checkFullyDefined();
10204 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10205 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
10206 const int *nodal3D=_nodal_connec->getConstPointer();
10207 const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
10208 int nbOfCells=getNumberOfCells();
10209 for(int i=0;i<nbOfCells;i++)
10211 std::map<int, std::set<int> > m;
10212 int offset=descIndx[i];
10213 int nbOfFaces=descIndx[i+1]-offset;
10216 for(int j=0;j<nbOfFaces;j++)
10218 const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
10219 if(p.first!=-1 && p.second!=-1)
10223 start=p.first; end=p.second;
10224 m[p.first].insert(p.second);
10225 m[p.second].insert(p.first);
10229 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
10230 int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
10231 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
10232 INTERP_KERNEL::NormalizedCellType cmsId;
10233 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
10234 start=tmp[0]; end=tmp[nbOfNodesSon-1];
10235 for(unsigned k=0;k<nbOfNodesSon;k++)
10237 m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
10238 m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
10245 std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
10249 std::map<int, std::set<int> >::const_iterator it=m.find(start);
10250 const std::set<int>& s=(*it).second;
10251 std::set<int> s2; s2.insert(prev);
10253 std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
10256 int val=*s3.begin();
10257 conn.push_back(start);
10264 conn.push_back(end);
10267 nodalRes->insertAtTheEnd(conn.begin(),conn.end());
10268 nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
10269 cellIds->pushBackSilent(i);
10275 * 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
10276 * 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
10277 * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
10278 * 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
10279 * 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.
10281 * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
10283 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
10285 std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
10288 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
10289 if(cm.getDimension()==2)
10291 const int *node=nodalConnBg+1;
10292 int startNode=*node++;
10293 double refX=coords[2*startNode];
10294 for(;node!=nodalConnEnd;node++)
10296 if(coords[2*(*node)]<refX)
10299 refX=coords[2*startNode];
10302 std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
10306 double angle0=-M_PI/2;
10311 double angleNext=0.;
10312 while(nextNode!=startNode)
10316 for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
10318 if(*node!=tmpOut.back() && *node!=prevNode)
10320 tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
10321 double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
10326 res=angle0-angleM+2.*M_PI;
10335 if(nextNode!=startNode)
10337 angle0=angleNext-M_PI;
10340 prevNode=tmpOut.back();
10341 tmpOut.push_back(nextNode);
10344 std::vector<int> tmp3(2*(sz-1));
10345 std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
10346 std::copy(nodalConnBg+1,nodalConnEnd,it);
10347 if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
10349 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10352 if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
10354 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10359 nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
10360 nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
10365 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10368 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10372 * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
10373 * 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.
10375 * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
10376 * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
10377 * \param [in,out] arr array in which the remove operation will be done.
10378 * \param [in,out] arrIndx array in the remove operation will modify
10379 * \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])
10380 * \return true if \b arr and \b arrIndx have been modified, false if not.
10382 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
10384 if(!arrIndx || !arr)
10385 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
10386 if(offsetForRemoval<0)
10387 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
10388 std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
10389 int nbOfGrps=arrIndx->getNumberOfTuples()-1;
10390 int *arrIPtr=arrIndx->getPointer();
10392 int previousArrI=0;
10393 const int *arrPtr=arr->getConstPointer();
10394 std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
10395 for(int i=0;i<nbOfGrps;i++,arrIPtr++)
10397 if(*arrIPtr-previousArrI>offsetForRemoval)
10399 for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
10401 if(s.find(*work)==s.end())
10402 arrOut.push_back(*work);
10405 previousArrI=*arrIPtr;
10406 *arrIPtr=(int)arrOut.size();
10408 if(arr->getNumberOfTuples()==(int)arrOut.size())
10410 arr->alloc((int)arrOut.size(),1);
10411 std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
10416 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10417 * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
10418 * The selection of extraction is done standardly in new2old format.
10419 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10421 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10422 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10423 * \param [in] arrIn arr origin array from which the extraction will be done.
10424 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10425 * \param [out] arrOut the resulting array
10426 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10427 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
10429 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10430 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10432 if(!arrIn || !arrIndxIn)
10433 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
10434 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10435 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10436 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
10437 std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
10438 const int *arrInPtr=arrIn->getConstPointer();
10439 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10440 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10442 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10443 int maxSizeOfArr=arrIn->getNumberOfTuples();
10444 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10445 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10446 arrIo->alloc((int)(sz+1),1);
10447 const int *idsIt=idsOfSelectBg;
10448 int *work=arrIo->getPointer();
10451 for(std::size_t i=0;i<sz;i++,work++,idsIt++)
10453 if(*idsIt>=0 && *idsIt<nbOfGrps)
10454 lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
10457 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10458 throw INTERP_KERNEL::Exception(oss.str().c_str());
10464 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
10465 oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
10466 throw INTERP_KERNEL::Exception(oss.str().c_str());
10469 arro->alloc(lgth,1);
10470 work=arro->getPointer();
10471 idsIt=idsOfSelectBg;
10472 for(std::size_t i=0;i<sz;i++,idsIt++)
10474 if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
10475 work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
10478 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
10479 oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10480 throw INTERP_KERNEL::Exception(oss.str().c_str());
10483 arrOut=arro.retn();
10484 arrIndexOut=arrIo.retn();
10488 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10489 * 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 ).
10490 * The selection of extraction is done standardly in new2old format.
10491 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10493 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10494 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10495 * \param [in] arrIn arr origin array from which the extraction will be done.
10496 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10497 * \param [out] arrOut the resulting array
10498 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10499 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
10501 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10502 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10504 if(!arrIn || !arrIndxIn)
10505 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
10506 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10507 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10508 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
10509 int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
10510 const int *arrInPtr=arrIn->getConstPointer();
10511 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10512 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10514 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10515 int maxSizeOfArr=arrIn->getNumberOfTuples();
10516 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10517 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10518 arrIo->alloc((int)(sz+1),1);
10519 int idsIt=idsOfSelectStart;
10520 int *work=arrIo->getPointer();
10523 for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
10525 if(idsIt>=0 && idsIt<nbOfGrps)
10526 lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
10529 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10530 throw INTERP_KERNEL::Exception(oss.str().c_str());
10536 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
10537 oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
10538 throw INTERP_KERNEL::Exception(oss.str().c_str());
10541 arro->alloc(lgth,1);
10542 work=arro->getPointer();
10543 idsIt=idsOfSelectStart;
10544 for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
10546 if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
10547 work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
10550 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
10551 oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10552 throw INTERP_KERNEL::Exception(oss.str().c_str());
10555 arrOut=arro.retn();
10556 arrIndexOut=arrIo.retn();
10560 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10561 * 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
10562 * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
10563 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
10565 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10566 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10567 * \param [in] arrIn arr origin array from which the extraction will be done.
10568 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10569 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
10570 * \param [in] srcArrIndex index array of \b srcArr
10571 * \param [out] arrOut the resulting array
10572 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10574 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
10576 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10577 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
10578 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10580 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10581 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
10582 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10583 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10584 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10585 std::vector<bool> v(nbOfTuples,true);
10587 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10588 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10589 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10591 if(*it>=0 && *it<nbOfTuples)
10594 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
10598 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
10599 throw INTERP_KERNEL::Exception(oss.str().c_str());
10602 srcArrIndexPtr=srcArrIndex->getConstPointer();
10603 arrIo->alloc(nbOfTuples+1,1);
10604 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
10605 const int *arrInPtr=arrIn->getConstPointer();
10606 const int *srcArrPtr=srcArr->getConstPointer();
10607 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
10608 int *arroPtr=arro->getPointer();
10609 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
10613 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
10614 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
10618 std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
10619 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
10620 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
10623 arrOut=arro.retn();
10624 arrIndexOut=arrIo.retn();
10628 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10629 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
10631 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10632 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10633 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
10634 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10635 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
10636 * \param [in] srcArrIndex index array of \b srcArr
10638 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
10640 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
10641 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
10643 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10644 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
10645 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10646 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10647 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10648 int *arrInOutPtr=arrInOut->getPointer();
10649 const int *srcArrPtr=srcArr->getConstPointer();
10650 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10652 if(*it>=0 && *it<nbOfTuples)
10654 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
10655 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
10658 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] !";
10659 throw INTERP_KERNEL::Exception(oss.str().c_str());
10664 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
10665 throw INTERP_KERNEL::Exception(oss.str().c_str());
10671 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
10672 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
10673 * 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]].
10674 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
10675 * A negative value in \b arrIn means that it is ignored.
10676 * 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.
10678 * \param [in] arrIn arr origin array from which the extraction will be done.
10679 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10680 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
10681 * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
10683 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
10685 int seed=0,nbOfDepthPeelingPerformed=0;
10686 return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
10690 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
10691 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
10692 * 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]].
10693 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
10694 * A negative value in \b arrIn means that it is ignored.
10695 * 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.
10696 * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
10697 * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
10698 * \param [in] arrIn arr origin array from which the extraction will be done.
10699 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10700 * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
10701 * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
10702 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
10703 * \sa MEDCouplingUMesh::partitionBySpreadZone
10705 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
10707 nbOfDepthPeelingPerformed=0;
10709 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
10710 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10713 DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
10717 std::vector<bool> fetched(nbOfTuples,false);
10718 return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
10721 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
10723 nbOfDepthPeelingPerformed=0;
10724 if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
10725 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
10726 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10727 std::vector<bool> fetched2(nbOfTuples,false);
10729 for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
10731 if(*seedElt>=0 && *seedElt<nbOfTuples)
10732 { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
10734 { 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()); }
10736 const int *arrInPtr=arrIn->getConstPointer();
10737 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10738 int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
10739 std::vector<int> idsToFetch1(seedBg,seedEnd);
10740 std::vector<int> idsToFetch2;
10741 std::vector<int> *idsToFetch=&idsToFetch1;
10742 std::vector<int> *idsToFetchOther=&idsToFetch2;
10743 while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
10745 for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
10746 for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
10748 { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
10749 std::swap(idsToFetch,idsToFetchOther);
10750 idsToFetchOther->clear();
10751 nbOfDepthPeelingPerformed++;
10753 int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
10755 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
10756 int *retPtr=ret->getPointer();
10757 for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
10764 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10765 * 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
10766 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
10767 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
10769 * \param [in] start begin of set of ids of the input extraction (included)
10770 * \param [in] end end of set of ids of the input extraction (excluded)
10771 * \param [in] step step of the set of ids in range mode.
10772 * \param [in] arrIn arr origin array from which the extraction will be done.
10773 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10774 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
10775 * \param [in] srcArrIndex index array of \b srcArr
10776 * \param [out] arrOut the resulting array
10777 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10779 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
10781 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10782 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
10783 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10785 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10786 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
10787 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10788 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10789 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10791 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10792 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10793 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
10795 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
10797 if(it>=0 && it<nbOfTuples)
10798 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
10801 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
10802 throw INTERP_KERNEL::Exception(oss.str().c_str());
10805 srcArrIndexPtr=srcArrIndex->getConstPointer();
10806 arrIo->alloc(nbOfTuples+1,1);
10807 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
10808 const int *arrInPtr=arrIn->getConstPointer();
10809 const int *srcArrPtr=srcArr->getConstPointer();
10810 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
10811 int *arroPtr=arro->getPointer();
10812 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
10814 int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
10817 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
10818 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
10822 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
10823 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
10826 arrOut=arro.retn();
10827 arrIndexOut=arrIo.retn();
10831 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10832 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
10834 * \param [in] start begin of set of ids of the input extraction (included)
10835 * \param [in] end end of set of ids of the input extraction (excluded)
10836 * \param [in] step step of the set of ids in range mode.
10837 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
10838 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10839 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
10840 * \param [in] srcArrIndex index array of \b srcArr
10842 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
10844 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
10845 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
10847 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10848 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
10849 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10850 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10851 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10852 int *arrInOutPtr=arrInOut->getPointer();
10853 const int *srcArrPtr=srcArr->getConstPointer();
10854 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
10856 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
10858 if(it>=0 && it<nbOfTuples)
10860 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
10861 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
10864 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
10865 throw INTERP_KERNEL::Exception(oss.str().c_str());
10870 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
10871 throw INTERP_KERNEL::Exception(oss.str().c_str());
10877 * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
10878 * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
10879 * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
10880 * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
10881 * The sum of measure field of returned mesh is equal to the sum of measure field of this.
10883 * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
10885 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
10887 checkFullyDefined();
10888 int mdim=getMeshDimension();
10889 int spaceDim=getSpaceDimension();
10891 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
10892 std::vector<DataArrayInt *> partition=partitionBySpreadZone();
10893 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
10894 std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
10895 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
10896 ret->setCoords(getCoords());
10897 ret->allocateCells((int)partition.size());
10899 for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
10901 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
10902 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
10906 cell=tmp->buildUnionOf2DMesh();
10909 cell=tmp->buildUnionOf3DMesh();
10912 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
10915 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
10918 ret->finishInsertingCells();
10923 * This method partitions \b this into contiguous zone.
10924 * This method only needs a well defined connectivity. Coordinates are not considered here.
10925 * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
10927 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
10929 int nbOfCellsCur=getNumberOfCells();
10930 std::vector<DataArrayInt *> ret;
10931 if(nbOfCellsCur<=0)
10933 DataArrayInt *neigh=0,*neighI=0;
10934 computeNeighborsOfCells(neigh,neighI);
10935 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
10936 std::vector<bool> fetchedCells(nbOfCellsCur,false);
10937 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
10939 while(seed<nbOfCellsCur)
10941 int nbOfPeelPerformed=0;
10942 ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
10943 seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
10945 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
10946 ret.push_back((*it).retn());
10951 * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
10952 * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
10954 * \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.
10955 * \return a newly allocated DataArrayInt to be managed by the caller.
10956 * \throw In case of \a code has not the right format (typically of size 3*n)
10958 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
10960 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
10961 std::size_t nb=code.size()/3;
10962 if(code.size()%3!=0)
10963 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
10964 ret->alloc((int)nb,2);
10965 int *retPtr=ret->getPointer();
10966 for(std::size_t i=0;i<nb;i++,retPtr+=2)
10968 retPtr[0]=code[3*i+2];
10969 retPtr[1]=code[3*i+2]+code[3*i+1];
10975 * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
10976 * All cells in \a this are expected to be linear 3D cells.
10977 * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
10978 * It leads to an increase to number of cells.
10979 * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
10980 * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints
10981 * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
10983 * \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.
10984 * For all other cells, the splitting policy will be ignored.
10985 * \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.
10986 * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
10987 * an id of old cell producing it. The caller is to delete this array using
10988 * decrRef() as it is no more needed.
10989 * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
10991 * \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
10992 * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
10994 * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
10995 * \throw If \a this is not fully constituted with linear 3D cells.
10996 * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
10998 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
11000 INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
11001 checkConnectivityFullyDefined();
11002 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
11003 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
11004 int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
11005 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
11006 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
11007 int *retPt(ret->getPointer());
11008 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
11009 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
11010 const int *oldc(_nodal_connec->begin());
11011 const int *oldci(_nodal_connec_index->begin());
11012 const double *coords(_coords->begin());
11013 for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
11015 std::vector<int> a; std::vector<double> b;
11016 INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
11017 std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
11018 const int *aa(&a[0]);
11021 for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
11023 *it=(-(*(it))-1+nbNodes);
11024 addPts->insertAtTheEnd(b.begin(),b.end());
11025 nbNodes+=(int)b.size()/3;
11027 for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
11028 newConn->insertAtTheEnd(aa,aa+4);
11030 if(!addPts->empty())
11032 addPts->rearrange(3);
11033 nbOfAdditionalPoints=addPts->getNumberOfTuples();
11034 addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
11035 ret0->setCoords(addPts);
11039 nbOfAdditionalPoints=0;
11040 ret0->setCoords(getCoords());
11042 ret0->setNodalConnectivity(newConn);
11044 ret->computeOffsets2();
11045 n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
11046 return ret0.retn();
11050 * 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).
11052 * \sa MEDCouplingUMesh::split2DCells
11054 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
11056 checkConnectivityFullyDefined();
11057 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
11058 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11059 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11060 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11061 int prevPosOfCi(ciPtr[0]);
11062 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11064 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
11065 *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
11066 for(int j=0;j<sz;j++)
11068 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
11069 for(int k=0;k<sz2;k++)
11070 *cPtr++=subPtr[offset2+k];
11072 *cPtr++=oldConn[prevPosOfCi+j+2];
11075 prevPosOfCi=ciPtr[1];
11076 ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11079 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
11080 _nodal_connec->decrRef();
11081 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
11084 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11090 int ret(nodesCnter++);
11092 e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
11093 addCoo.insertAtTheEnd(newPt,newPt+2);
11100 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)
11103 int trueStart(start>=0?start:nbOfEdges+start);
11104 tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
11105 newConnOfCell->insertAtTheEnd(tmp,tmp+3);
11110 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11111 InternalAddPoint(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
11112 middles.push_back(tmp3+offset);
11115 middles.push_back(connBg[trueStart+nbOfEdges]);
11119 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)
11121 int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
11122 newConnOfCell->pushBackSilent(tmpEnd);
11127 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11128 InternalAddPoint(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11129 middles.push_back(tmp3+offset);
11132 middles.push_back(connBg[start+nbOfEdges]);
11136 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)
11142 int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
11143 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11144 InternalAddPoint(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11145 middles.push_back(tmp3+offset);
11148 middles.push_back(connBg[start+nbOfEdges]);
11155 * 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 ) .
11156 * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
11158 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
11160 std::size_t sz(std::distance(connBg,connEnd));
11161 if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
11162 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
11164 INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
11165 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
11166 unsigned nbs(cm.getNumberOfSons2(connBg+1,sz)),nbOfHit(0);
11167 int posBaseElt(0),posEndElt(0),nbOfTurn(0);
11168 INTERP_KERNEL::NormalizedCellType typeOfSon;
11169 std::vector<int> middles;
11171 for(;nbOfHit<nbs;nbOfTurn++)
11173 cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
11174 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
11175 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11178 unsigned endI(nbs-nbOfHit);
11179 for(unsigned i=0;i<endI;i++)
11181 cm.fillSonCellNodalConnectivity2(posBaseElt+(int)i+1,connBg+1,sz,tmpConn,typeOfSon);
11182 INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11183 INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11184 bool isColinear(eint->areColinears());
11196 {//look if the first edge of cell is not colinear with last edges in this case the start of nodal connectivity is shifted back
11197 unsigned endII(nbs-nbOfHit-1);//warning nbOfHit can be modified, so put end condition in a variable.
11198 for(unsigned ii=0;ii<endII;ii++)
11200 cm.fillSonCellNodalConnectivity2(nbs-ii-1,connBg+1,sz,tmpConn,typeOfSon);
11201 eCand=MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m);
11202 eint=INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand);
11203 isColinear=eint->areColinears();
11219 //push [posBaseElt,posEndElt) in newConnOfCell using e
11221 EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11222 else if(nbOfHit!=nbs)
11223 EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11225 EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11226 posBaseElt=posEndElt;
11229 if(!middles.empty())
11230 newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
11235 * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
11237 * \return int - the number of new nodes created.
11238 * \sa MEDCouplingUMesh::split2DCells
11240 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
11243 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
11244 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11245 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
11246 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11247 const int *midPtr(mid->begin()),*midIPtr(midI->begin());
11248 const double *oldCoordsPtr(getCoords()->begin());
11249 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11250 int prevPosOfCi(ciPtr[0]);
11251 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11253 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
11254 for(int j=0;j<sz;j++)
11255 { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
11256 *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
11257 for(int j=0;j<sz;j++)//loop over subedges of oldConn
11259 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
11263 cPtr[1]=oldConn[prevPosOfCi+2+j];
11264 cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
11267 std::vector<INTERP_KERNEL::Node *> ns(3);
11268 ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
11269 ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
11270 ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
11271 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
11272 for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
11274 cPtr[1]=subPtr[offset2+k];
11275 cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
11277 int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
11279 { cPtr[1]=tmpEnd; }
11280 cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
11282 prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
11283 ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11286 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
11287 _nodal_connec->decrRef();
11288 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
11289 addCoo->rearrange(2);
11290 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
11292 return addCoo->getNumberOfTuples();
11295 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
11296 _own_cell(true),_cell_id(-1),_nb_cell(0)
11301 _nb_cell=mesh->getNumberOfCells();
11305 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
11313 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
11314 _own_cell(false),_cell_id(bg-1),
11321 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
11324 if(_cell_id<_nb_cell)
11333 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
11339 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
11341 return new MEDCouplingUMeshCellByTypeIterator(_mesh);
11344 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
11350 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
11358 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
11364 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
11369 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
11374 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
11376 return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
11379 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
11384 _nb_cell=mesh->getNumberOfCells();
11388 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
11395 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
11397 const int *c=_mesh->getNodalConnectivity()->getConstPointer();
11398 const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
11399 if(_cell_id<_nb_cell)
11401 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
11402 int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
11403 int startId=_cell_id;
11404 _cell_id+=nbOfElems;
11405 return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
11411 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
11415 _conn=mesh->getNodalConnectivity()->getPointer();
11416 _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
11420 void MEDCouplingUMeshCell::next()
11422 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11427 _conn_lgth=_conn_indx[1]-_conn_indx[0];
11430 std::string MEDCouplingUMeshCell::repr() const
11432 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11434 std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
11436 std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
11440 return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
11443 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
11445 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11446 return (INTERP_KERNEL::NormalizedCellType)_conn[0];
11448 return INTERP_KERNEL::NORM_ERROR;
11451 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
11454 if(_conn_lgth!=NOTICABLE_FIRST_VAL)