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();
1429 int nbOfCells=getNumberOfCells();
1430 const int *connIndex=_nodal_connec_index->getConstPointer();
1431 const int *conn=_nodal_connec->getConstPointer();
1432 for(int i=0;i<nbOfCells;i++)
1433 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1436 if(conn[j]<nbOfNodes)
1437 nodeIdsInUse[conn[j]]=true;
1440 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1441 throw INTERP_KERNEL::Exception(oss.str().c_str());
1447 * Finds nodes not used in any cell and returns an array giving a new id to every node
1448 * by excluding the unused nodes, for which the array holds -1. The result array is
1449 * a mapping in "Old to New" mode.
1450 * \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1451 * \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1452 * this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1453 * if the node is unused or a new id else. The caller is to delete this
1454 * array using decrRef() as it is no more needed.
1455 * \throw If the coordinates array is not set.
1456 * \throw If the nodal connectivity of cells is not defined.
1457 * \throw If the nodal connectivity includes an invalid id.
1459 * \if ENABLE_EXAMPLES
1460 * \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1461 * \ref py_mcumesh_getNodeIdsInUse "Here is a Python example".
1463 * \sa computeNodeIdsAlg()
1465 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1468 int nbOfNodes=getNumberOfNodes();
1469 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1470 ret->alloc(nbOfNodes,1);
1471 int *traducer=ret->getPointer();
1472 std::fill(traducer,traducer+nbOfNodes,-1);
1473 int nbOfCells=getNumberOfCells();
1474 const int *connIndex=_nodal_connec_index->getConstPointer();
1475 const int *conn=_nodal_connec->getConstPointer();
1476 for(int i=0;i<nbOfCells;i++)
1477 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1480 if(conn[j]<nbOfNodes)
1481 traducer[conn[j]]=1;
1484 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1485 throw INTERP_KERNEL::Exception(oss.str().c_str());
1488 nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1489 std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1494 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1495 * For each cell in \b this the number of nodes constituting cell is computed.
1496 * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1497 * So for pohyhedrons some nodes can be counted several times in the returned result.
1499 * \return a newly allocated array
1500 * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1502 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1504 checkConnectivityFullyDefined();
1505 int nbOfCells=getNumberOfCells();
1506 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1507 ret->alloc(nbOfCells,1);
1508 int *retPtr=ret->getPointer();
1509 const int *conn=getNodalConnectivity()->getConstPointer();
1510 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1511 for(int i=0;i<nbOfCells;i++,retPtr++)
1513 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1514 *retPtr=connI[i+1]-connI[i]-1;
1516 *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1522 * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1523 * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1525 * \return DataArrayInt * - new object to be deallocated by the caller.
1526 * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1528 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1530 checkConnectivityFullyDefined();
1531 int nbOfCells=getNumberOfCells();
1532 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1533 ret->alloc(nbOfCells,1);
1534 int *retPtr=ret->getPointer();
1535 const int *conn=getNodalConnectivity()->getConstPointer();
1536 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1537 for(int i=0;i<nbOfCells;i++,retPtr++)
1539 std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1540 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1541 *retPtr=(int)s.size();
1545 *retPtr=(int)s.size();
1552 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1553 * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1555 * \return a newly allocated array
1557 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1559 checkConnectivityFullyDefined();
1560 int nbOfCells=getNumberOfCells();
1561 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1562 ret->alloc(nbOfCells,1);
1563 int *retPtr=ret->getPointer();
1564 const int *conn=getNodalConnectivity()->getConstPointer();
1565 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1566 for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1568 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1569 *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1575 * Removes unused nodes (the node coordinates array is shorten) and returns an array
1576 * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1577 * array mean that the corresponding old node is no more used.
1578 * \return DataArrayInt * - a new instance of DataArrayInt of length \a
1579 * this->getNumberOfNodes() before call of this method. The caller is to
1580 * delete this array using decrRef() as it is no more needed.
1581 * \throw If the coordinates array is not set.
1582 * \throw If the nodal connectivity of cells is not defined.
1583 * \throw If the nodal connectivity includes an invalid id.
1585 * \if ENABLE_EXAMPLES
1586 * \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1587 * \ref py_mcumesh_zipCoordsTraducer "Here is a Python example".
1590 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1592 return MEDCouplingPointSet::zipCoordsTraducer();
1596 * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1597 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1599 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1604 return AreCellsEqual0(conn,connI,cell1,cell2);
1606 return AreCellsEqual1(conn,connI,cell1,cell2);
1608 return AreCellsEqual2(conn,connI,cell1,cell2);
1610 return AreCellsEqual3(conn,connI,cell1,cell2);
1612 return AreCellsEqual7(conn,connI,cell1,cell2);
1614 throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1618 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1620 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1622 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1623 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1628 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1630 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1632 int sz=connI[cell1+1]-connI[cell1];
1633 if(sz==connI[cell2+1]-connI[cell2])
1635 if(conn[connI[cell1]]==conn[connI[cell2]])
1637 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1638 unsigned dim=cm.getDimension();
1644 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1645 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1646 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1647 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1648 return work!=tmp+sz1?1:0;
1651 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1654 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1661 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1663 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1665 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1667 if(conn[connI[cell1]]==conn[connI[cell2]])
1669 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1670 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1678 * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1680 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1682 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1684 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1685 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1692 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1694 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1696 int sz=connI[cell1+1]-connI[cell1];
1697 if(sz==connI[cell2+1]-connI[cell2])
1699 if(conn[connI[cell1]]==conn[connI[cell2]])
1701 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1702 unsigned dim=cm.getDimension();
1708 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1709 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1710 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1711 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1716 std::reverse_iterator<int *> it1((int *)tmp+sz1);
1717 std::reverse_iterator<int *> it2((int *)tmp);
1718 if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1724 return work!=tmp+sz1?1:0;
1727 {//case of SEG2 and SEG3
1728 if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1730 if(!cm.isQuadratic())
1732 std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1733 std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1734 if(std::equal(it1,it2,conn+connI[cell2]+1))
1740 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])
1747 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1754 * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1755 * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1756 * and result remains unchanged.
1757 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1758 * If in 'candidates' pool -1 value is considered as an empty value.
1759 * WARNING this method returns only ONE set of result !
1761 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1763 if(candidates.size()<1)
1766 std::vector<int>::const_iterator iter=candidates.begin();
1767 int start=(*iter++);
1768 for(;iter!=candidates.end();iter++)
1770 int status=AreCellsEqual(conn,connI,start,*iter,compType);
1775 result->pushBackSilent(start);
1779 result->pushBackSilent(*iter);
1781 result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1788 * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1789 * This method keeps the coordiantes of \a this. This method is time consuming and is called
1791 * \param [in] compType input specifying the technique used to compare cells each other.
1792 * - 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.
1793 * - 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)
1794 * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1795 * - 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
1796 * can be used for users not sensitive to orientation of cell
1797 * \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.
1798 * \param [out] commonCells
1799 * \param [out] commonCellsI
1800 * \return the correspondance array old to new in a newly allocated array.
1803 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1805 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1806 getReverseNodalConnectivity(revNodal,revNodalI);
1807 FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1810 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1811 DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr)
1813 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1814 int nbOfCells=nodalI->getNumberOfTuples()-1;
1815 commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1816 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1817 const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1818 std::vector<bool> isFetched(nbOfCells,false);
1821 for(int i=0;i<nbOfCells;i++)
1825 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1826 std::vector<int> v,v2;
1827 if(connOfNode!=connPtr+connIPtr[i+1])
1829 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1830 v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1833 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1837 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1838 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1839 v2.resize(std::distance(v2.begin(),it));
1843 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1845 int pos=commonCellsI->back();
1846 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1847 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1848 isFetched[*it]=true;
1856 for(int i=startCellId;i<nbOfCells;i++)
1860 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1861 std::vector<int> v,v2;
1862 if(connOfNode!=connPtr+connIPtr[i+1])
1864 v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1867 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1871 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1872 v2.resize(std::distance(v2.begin(),it));
1876 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1878 int pos=commonCellsI->back();
1879 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1880 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1881 isFetched[*it]=true;
1887 commonCellsArr=commonCells.retn();
1888 commonCellsIArr=commonCellsI.retn();
1892 * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1893 * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1894 * than \a other->getNumberOfCells() in the returned array means that there is no
1895 * corresponding cell in \a this mesh.
1896 * It is expected that \a this and \a other meshes share the same node coordinates
1897 * array, if it is not so an exception is thrown.
1898 * \param [in] other - the mesh to compare with.
1899 * \param [in] compType - specifies a cell comparison technique. For meaning of its
1900 * valid values [0,1,2], see zipConnectivityTraducer().
1901 * \param [out] arr - a new instance of DataArrayInt returning correspondence
1902 * between cells of the two meshes. It contains \a other->getNumberOfCells()
1903 * values. The caller is to delete this array using
1904 * decrRef() as it is no more needed.
1905 * \return bool - \c true if all cells of \a other mesh are present in the \a this
1908 * \if ENABLE_EXAMPLES
1909 * \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1910 * \ref py_mcumesh_areCellsIncludedIn "Here is a Python example".
1912 * \sa checkDeepEquivalOnSameNodesWith()
1913 * \sa checkGeoEquivalWith()
1915 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1917 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1918 int nbOfCells=getNumberOfCells();
1919 static const int possibleCompType[]={0,1,2};
1920 if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1922 std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1923 std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1925 throw INTERP_KERNEL::Exception(oss.str().c_str());
1927 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1928 arr=o2n->substr(nbOfCells);
1929 arr->setName(other->getName());
1931 if(other->getNumberOfCells()==0)
1933 return arr->getMaxValue(tmp)<nbOfCells;
1937 * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1938 * This method tries to determine if \b other is fully included in \b this.
1939 * The main difference is that this method is not expected to throw exception.
1940 * This method has two outputs :
1942 * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1943 * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1945 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1947 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1948 DataArrayInt *commonCells=0,*commonCellsI=0;
1949 int thisNbCells=getNumberOfCells();
1950 mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1951 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1952 const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1953 int otherNbCells=other->getNumberOfCells();
1954 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1955 arr2->alloc(otherNbCells,1);
1956 arr2->fillWithZero();
1957 int *arr2Ptr=arr2->getPointer();
1958 int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1959 for(int i=0;i<nbOfCommon;i++)
1961 int start=commonCellsPtr[commonCellsIPtr[i]];
1962 if(start<thisNbCells)
1964 for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1966 int sig=commonCellsPtr[j]>0?1:-1;
1967 int val=std::abs(commonCellsPtr[j])-1;
1968 if(val>=thisNbCells)
1969 arr2Ptr[val-thisNbCells]=sig*(start+1);
1973 arr2->setName(other->getName());
1974 if(arr2->presenceOfValue(0))
1980 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1983 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1984 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1986 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1987 std::vector<const MEDCouplingUMesh *> ms(2);
1990 return MergeUMeshesOnSameCoords(ms);
1994 * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1995 * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1996 * cellIds is not given explicitely but by a range python like.
1998 * \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.
1999 * \return a newly allocated
2001 * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
2002 * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
2004 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const
2006 if(getMeshDimension()!=-1)
2007 return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
2010 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
2012 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2014 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2016 return const_cast<MEDCouplingUMesh *>(this);
2021 * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
2022 * The result mesh shares or not the node coordinates array with \a this mesh depending
2023 * on \a keepCoords parameter.
2024 * \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
2025 * to write this mesh to the MED file, its cells must be sorted using
2026 * sortCellsInMEDFileFrmt().
2027 * \param [in] begin - an array of cell ids to include to the new mesh.
2028 * \param [in] end - a pointer to last-plus-one-th element of \a begin.
2029 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2030 * array of \a this mesh, else "free" nodes are removed from the result mesh
2031 * by calling zipCoords().
2032 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2033 * to delete this mesh using decrRef() as it is no more needed.
2034 * \throw If the coordinates array is not set.
2035 * \throw If the nodal connectivity of cells is not defined.
2036 * \throw If any cell id in the array \a begin is not valid.
2038 * \if ENABLE_EXAMPLES
2039 * \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
2040 * \ref py_mcumesh_buildPartOfMySelf "Here is a Python example".
2043 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2045 if(getMeshDimension()!=-1)
2046 return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
2050 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2052 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2054 return const_cast<MEDCouplingUMesh *>(this);
2059 * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2061 * 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.
2062 * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2063 * The number of cells of \b this will remain the same with this method.
2065 * \param [in] begin begin of cell ids (included) of cells in this to assign
2066 * \param [in] end end of cell ids (excluded) of cells in this to assign
2067 * \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 ).
2068 * Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2070 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2072 checkConnectivityFullyDefined();
2073 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2074 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2075 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2076 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2078 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2079 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2080 throw INTERP_KERNEL::Exception(oss.str().c_str());
2082 int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2083 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2085 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2086 throw INTERP_KERNEL::Exception(oss.str().c_str());
2088 int nbOfCells=getNumberOfCells();
2089 bool easyAssign=true;
2090 const int *connI=_nodal_connec_index->getConstPointer();
2091 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2092 for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2094 if(*it>=0 && *it<nbOfCells)
2096 easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2100 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2101 throw INTERP_KERNEL::Exception(oss.str().c_str());
2106 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2111 DataArrayInt *arrOut=0,*arrIOut=0;
2112 MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2114 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2115 setConnectivity(arrOut,arrIOut,true);
2119 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2121 checkConnectivityFullyDefined();
2122 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2123 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2124 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2125 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2127 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2128 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2129 throw INTERP_KERNEL::Exception(oss.str().c_str());
2131 int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2132 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2134 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2135 throw INTERP_KERNEL::Exception(oss.str().c_str());
2137 int nbOfCells=getNumberOfCells();
2138 bool easyAssign=true;
2139 const int *connI=_nodal_connec_index->getConstPointer();
2140 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2142 for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2144 if(it>=0 && it<nbOfCells)
2146 easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2150 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2151 throw INTERP_KERNEL::Exception(oss.str().c_str());
2156 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2161 DataArrayInt *arrOut=0,*arrIOut=0;
2162 MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2164 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2165 setConnectivity(arrOut,arrIOut,true);
2170 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2171 * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2172 * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2173 * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2175 * \param [in] begin input start of array of node ids.
2176 * \param [in] end input end of array of node ids.
2177 * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2178 * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2180 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2182 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2183 checkConnectivityFullyDefined();
2185 int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2186 std::vector<bool> fastFinder(sz,false);
2187 for(const int *work=begin;work!=end;work++)
2188 if(*work>=0 && *work<sz)
2189 fastFinder[*work]=true;
2190 int nbOfCells=getNumberOfCells();
2191 const int *conn=getNodalConnectivity()->getConstPointer();
2192 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2193 for(int i=0;i<nbOfCells;i++)
2195 int ref=0,nbOfHit=0;
2196 for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2200 if(fastFinder[*work2])
2203 if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2204 cellIdsKept->pushBackSilent(i);
2206 cellIdsKeptArr=cellIdsKept.retn();
2210 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2211 * this->getMeshDimension(), that bound some cells of \a this mesh.
2212 * The cells of lower dimension to include to the result mesh are selected basing on
2213 * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2214 * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2215 * ==\c false, a cell is copied if any its node is in the array of node ids. The
2216 * created mesh shares the node coordinates array with \a this mesh.
2217 * \param [in] begin - the array of node ids.
2218 * \param [in] end - a pointer to the (last+1)-th element of \a begin.
2219 * \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2220 * array \a begin are added, else cells whose any node is in the
2221 * array \a begin are added.
2222 * \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2223 * to delete this mesh using decrRef() as it is no more needed.
2224 * \throw If the coordinates array is not set.
2225 * \throw If the nodal connectivity of cells is not defined.
2226 * \throw If any node id in \a begin is not valid.
2228 * \if ENABLE_EXAMPLES
2229 * \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2230 * \ref py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2233 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2235 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2236 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2237 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2238 desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2239 return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2243 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2244 * this->getMeshDimension(), which bound only one cell of \a this mesh.
2245 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2246 * array of \a this mesh, else "free" nodes are removed from the result mesh
2247 * by calling zipCoords().
2248 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2249 * to delete this mesh using decrRef() as it is no more needed.
2250 * \throw If the coordinates array is not set.
2251 * \throw If the nodal connectivity of cells is not defined.
2253 * \if ENABLE_EXAMPLES
2254 * \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2255 * \ref py_mcumesh_buildBoundaryMesh "Here is a Python example".
2258 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2260 DataArrayInt *desc=DataArrayInt::New();
2261 DataArrayInt *descIndx=DataArrayInt::New();
2262 DataArrayInt *revDesc=DataArrayInt::New();
2263 DataArrayInt *revDescIndx=DataArrayInt::New();
2265 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2268 descIndx->decrRef();
2269 int nbOfCells=meshDM1->getNumberOfCells();
2270 const int *revDescIndxC=revDescIndx->getConstPointer();
2271 std::vector<int> boundaryCells;
2272 for(int i=0;i<nbOfCells;i++)
2273 if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2274 boundaryCells.push_back(i);
2275 revDescIndx->decrRef();
2276 MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2281 * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2282 * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2283 * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown.
2285 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2287 checkFullyDefined();
2288 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2289 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2290 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2291 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2293 buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2294 desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2296 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2297 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2298 const int *revDescPtr=revDesc->getConstPointer();
2299 const int *revDescIndxPtr=revDescIndx->getConstPointer();
2300 int nbOfCells=getNumberOfCells();
2301 std::vector<bool> ret1(nbOfCells,false);
2303 for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2304 if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2305 { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2307 DataArrayInt *ret2=DataArrayInt::New();
2309 int *ret2Ptr=ret2->getPointer();
2311 for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2314 ret2->setName("BoundaryCells");
2319 * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2320 * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2321 * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2322 * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2324 * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2325 * This method method returns cells ids set s = s1 + s2 where :
2327 * - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2328 * - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2330 * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2331 * are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2333 * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2334 * \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
2335 * cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2337 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2339 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2340 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2341 checkConnectivityFullyDefined();
2342 otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2343 if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2344 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2345 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2346 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2347 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2348 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2349 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2350 const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2351 DataArrayInt *idsOtherInConsti=0;
2352 bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2353 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2355 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2357 for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2358 s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2359 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2360 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2361 DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2362 ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2363 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2364 ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2365 neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2366 RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2367 neighThisPartAuto=0;
2368 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2369 const int li[2]={0,1};
2370 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2371 s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2372 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2375 cellIdsRk0=s0arr.retn();
2376 cellIdsRk1=s_renum1.retn();
2380 * 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
2381 * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2383 * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2385 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2387 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2388 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2389 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2390 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2392 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2393 revDesc=0; desc=0; descIndx=0;
2394 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2395 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2396 return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2400 * Finds nodes lying on the boundary of \a this mesh.
2401 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2402 * nodes. The caller is to delete this array using decrRef() as it is no
2404 * \throw If the coordinates array is not set.
2405 * \throw If the nodal connectivity of cells is node defined.
2407 * \if ENABLE_EXAMPLES
2408 * \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2409 * \ref py_mcumesh_findBoundaryNodes "Here is a Python example".
2412 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2414 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2415 return skin->computeFetchedNodeIds();
2418 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2421 return const_cast<MEDCouplingUMesh *>(this);
2425 * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2426 * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2427 * 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.
2428 * 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.
2429 * 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.
2431 * \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
2432 * parameter is altered during the call.
2433 * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2434 * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2435 * \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.
2437 * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2439 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2440 DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const
2442 checkFullyDefined();
2443 otherDimM1OnSameCoords.checkFullyDefined();
2444 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2445 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2446 if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2447 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2448 DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2449 findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2450 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2451 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2452 s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2453 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2454 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2455 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2456 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2457 cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2459 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2460 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2461 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2462 DataArrayInt *idsTmp=0;
2463 bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2464 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2466 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2467 MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2468 DataArrayInt *tmp0=0,*tmp1=0;
2469 ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2470 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2471 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2472 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2473 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2474 cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2475 cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2477 cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2478 cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2479 nodeIdsToDuplicate=s3.retn();
2483 * This method operates a modification of the connectivity and coords in \b this.
2484 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2485 * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2486 * 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
2487 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2488 * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2490 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2492 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2493 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2495 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2497 int nbOfNodes=getNumberOfNodes();
2498 duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2499 duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2503 * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2504 * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2505 * This method is a generalization of shiftNodeNumbersInConn().
2506 * \warning This method performs no check of validity of new ids. **Use it with care !**
2507 * \param [in] newNodeNumbersO2N - a permutation array, of length \a
2508 * this->getNumberOfNodes(), in "Old to New" mode.
2509 * See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2510 * \throw If the nodal connectivity of cells is not defined.
2512 * \if ENABLE_EXAMPLES
2513 * \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2514 * \ref py_mcumesh_renumberNodesInConn "Here is a Python example".
2517 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2519 checkConnectivityFullyDefined();
2520 int *conn=getNodalConnectivity()->getPointer();
2521 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2522 int nbOfCells=getNumberOfCells();
2523 for(int i=0;i<nbOfCells;i++)
2524 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2526 int& node=conn[iconn];
2527 if(node>=0)//avoid polyhedron separator
2529 node=newNodeNumbersO2N[node];
2532 _nodal_connec->declareAsNew();
2537 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2538 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2539 * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2541 * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2543 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2545 checkConnectivityFullyDefined();
2546 int *conn=getNodalConnectivity()->getPointer();
2547 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2548 int nbOfCells=getNumberOfCells();
2549 for(int i=0;i<nbOfCells;i++)
2550 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2552 int& node=conn[iconn];
2553 if(node>=0)//avoid polyhedron separator
2558 _nodal_connec->declareAsNew();
2563 * This method operates a modification of the connectivity in \b this.
2564 * 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.
2565 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2566 * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2567 * 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
2568 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2569 * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2571 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2572 * As an another consequense after the call of this method \b this can be transiently non cohrent.
2574 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2575 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2576 * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ).
2578 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2580 checkConnectivityFullyDefined();
2581 std::map<int,int> m;
2583 for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2585 int *conn=getNodalConnectivity()->getPointer();
2586 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2587 int nbOfCells=getNumberOfCells();
2588 for(int i=0;i<nbOfCells;i++)
2589 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2591 int& node=conn[iconn];
2592 if(node>=0)//avoid polyhedron separator
2594 std::map<int,int>::iterator it=m.find(node);
2603 * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2605 * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2606 * After the call of this method the number of cells remains the same as before.
2608 * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2609 * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2610 * be strictly in [0;this->getNumberOfCells()).
2612 * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2613 * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2614 * should be contained in[0;this->getNumberOfCells()).
2616 * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2618 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2620 checkConnectivityFullyDefined();
2621 int nbCells=getNumberOfCells();
2622 const int *array=old2NewBg;
2624 array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2626 const int *conn=_nodal_connec->getConstPointer();
2627 const int *connI=_nodal_connec_index->getConstPointer();
2628 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2629 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2630 const int *n2oPtr=n2o->begin();
2631 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2632 newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2633 newConn->copyStringInfoFrom(*_nodal_connec);
2634 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2635 newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2636 newConnI->copyStringInfoFrom(*_nodal_connec_index);
2638 int *newC=newConn->getPointer();
2639 int *newCI=newConnI->getPointer();
2642 for(int i=0;i<nbCells;i++)
2645 int nbOfElts=connI[pos+1]-connI[pos];
2646 newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2651 setConnectivity(newConn,newConnI);
2653 free(const_cast<int *>(array));
2657 * Finds cells whose bounding boxes intersect a given bounding box.
2658 * \param [in] bbox - an array defining the bounding box via coordinates of its
2659 * extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2661 * \param [in] eps - a factor used to increase size of the bounding box of cell
2662 * before comparing it with \a bbox. This factor is multiplied by the maximal
2663 * extent of the bounding box of cell to produce an addition to this bounding box.
2664 * \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2665 * cells. The caller is to delete this array using decrRef() as it is no more
2667 * \throw If the coordinates array is not set.
2668 * \throw If the nodal connectivity of cells is not defined.
2670 * \if ENABLE_EXAMPLES
2671 * \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2672 * \ref py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2675 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2677 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2678 if(getMeshDimension()==-1)
2680 elems->pushBackSilent(0);
2681 return elems.retn();
2683 int dim=getSpaceDimension();
2684 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2685 const int* conn = getNodalConnectivity()->getConstPointer();
2686 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2687 const double* coords = getCoords()->getConstPointer();
2688 int nbOfCells=getNumberOfCells();
2689 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2691 for (int i=0; i<dim; i++)
2693 elem_bb[i*2]=std::numeric_limits<double>::max();
2694 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2697 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2699 int node= conn[inode];
2700 if(node>=0)//avoid polyhedron separator
2702 for (int idim=0; idim<dim; idim++)
2704 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2706 elem_bb[idim*2] = coords[node*dim+idim] ;
2708 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2710 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2715 if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2716 elems->pushBackSilent(ielem);
2718 return elems.retn();
2722 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2723 * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2724 * added in 'elems' parameter.
2726 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2728 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2729 if(getMeshDimension()==-1)
2731 elems->pushBackSilent(0);
2732 return elems.retn();
2734 int dim=getSpaceDimension();
2735 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2736 const int* conn = getNodalConnectivity()->getConstPointer();
2737 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2738 const double* coords = getCoords()->getConstPointer();
2739 int nbOfCells=getNumberOfCells();
2740 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2742 for (int i=0; i<dim; i++)
2744 elem_bb[i*2]=std::numeric_limits<double>::max();
2745 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2748 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2750 int node= conn[inode];
2751 if(node>=0)//avoid polyhedron separator
2753 for (int idim=0; idim<dim; idim++)
2755 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2757 elem_bb[idim*2] = coords[node*dim+idim] ;
2759 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2761 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2766 if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2767 elems->pushBackSilent(ielem);
2769 return elems.retn();
2773 * Returns a type of a cell by its id.
2774 * \param [in] cellId - the id of the cell of interest.
2775 * \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2776 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2778 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2780 const int *ptI=_nodal_connec_index->getConstPointer();
2781 const int *pt=_nodal_connec->getConstPointer();
2782 if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2783 return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2786 std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2787 throw INTERP_KERNEL::Exception(oss.str().c_str());
2792 * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2793 * This method does not throw exception if geometric type \a type is not in \a this.
2794 * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2795 * The coordinates array is not considered here.
2797 * \param [in] type the geometric type
2798 * \return cell ids in this having geometric type \a type.
2800 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2803 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2805 checkConnectivityFullyDefined();
2806 int nbCells=getNumberOfCells();
2807 int mdim=getMeshDimension();
2808 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2809 if(mdim!=(int)cm.getDimension())
2810 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2811 const int *ptI=_nodal_connec_index->getConstPointer();
2812 const int *pt=_nodal_connec->getConstPointer();
2813 for(int i=0;i<nbCells;i++)
2815 if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2816 ret->pushBackSilent(i);
2822 * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2824 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2826 const int *ptI=_nodal_connec_index->getConstPointer();
2827 const int *pt=_nodal_connec->getConstPointer();
2828 int nbOfCells=getNumberOfCells();
2830 for(int i=0;i<nbOfCells;i++)
2831 if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2837 * Returns the nodal connectivity of a given cell.
2838 * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2839 * all returned node ids can be used in getCoordinatesOfNode().
2840 * \param [in] cellId - an id of the cell of interest.
2841 * \param [in,out] conn - a vector where the node ids are appended. It is not
2842 * cleared before the appending.
2843 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2845 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2847 const int *ptI=_nodal_connec_index->getConstPointer();
2848 const int *pt=_nodal_connec->getConstPointer();
2849 for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2854 std::string MEDCouplingUMesh::simpleRepr() const
2856 static const char msg0[]="No coordinates specified !";
2857 std::ostringstream ret;
2858 ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2859 ret << "Description of mesh : \"" << getDescription() << "\"\n";
2861 double tt=getTime(tmpp1,tmpp2);
2862 ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2863 ret << "Iteration : " << tmpp1 << " Order : " << tmpp2 << "\n";
2865 { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2867 { ret << " Mesh dimension has not been set or is invalid !"; }
2870 const int spaceDim=getSpaceDimension();
2871 ret << spaceDim << "\nInfo attached on space dimension : ";
2872 for(int i=0;i<spaceDim;i++)
2873 ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2877 ret << msg0 << "\n";
2878 ret << "Number of nodes : ";
2880 ret << getNumberOfNodes() << "\n";
2882 ret << msg0 << "\n";
2883 ret << "Number of cells : ";
2884 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2885 ret << getNumberOfCells() << "\n";
2887 ret << "No connectivity specified !" << "\n";
2888 ret << "Cell types present : ";
2889 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2891 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2892 ret << cm.getRepr() << " ";
2898 std::string MEDCouplingUMesh::advancedRepr() const
2900 std::ostringstream ret;
2901 ret << simpleRepr();
2902 ret << "\nCoordinates array : \n___________________\n\n";
2904 _coords->reprWithoutNameStream(ret);
2906 ret << "No array set !\n";
2907 ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2908 reprConnectivityOfThisLL(ret);
2913 * This method returns a C++ code that is a dump of \a this.
2914 * This method will throw if this is not fully defined.
2916 std::string MEDCouplingUMesh::cppRepr() const
2918 static const char coordsName[]="coords";
2919 static const char connName[]="conn";
2920 static const char connIName[]="connI";
2921 checkFullyDefined();
2922 std::ostringstream ret; ret << "// coordinates" << std::endl;
2923 _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2924 _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2925 _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2926 ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2927 ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2928 ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2929 ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2933 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2935 std::ostringstream ret;
2936 reprConnectivityOfThisLL(ret);
2941 * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
2942 * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2943 * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2946 * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2947 * 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
2948 * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2950 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
2952 int mdim=getMeshDimension();
2954 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2955 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
2956 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
2957 bool needToCpyCT=true;
2960 tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2968 if(!_nodal_connec_index)
2970 tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2975 tmp2=_nodal_connec_index;
2978 ret->setConnectivity(tmp1,tmp2,false);
2983 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2984 ret->setCoords(coords);
2987 ret->setCoords(_coords);
2991 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
2993 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2995 int nbOfCells=getNumberOfCells();
2996 const int *c=_nodal_connec->getConstPointer();
2997 const int *ci=_nodal_connec_index->getConstPointer();
2998 for(int i=0;i<nbOfCells;i++)
3000 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3001 stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3002 std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3007 stream << "Connectivity not defined !\n";
3010 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3012 const int *ptI=_nodal_connec_index->getConstPointer();
3013 const int *pt=_nodal_connec->getConstPointer();
3014 if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3015 return ptI[cellId+1]-ptI[cellId]-1;
3017 return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3021 * Returns types of cells of the specified part of \a this mesh.
3022 * This method avoids computing sub-mesh explicitely to get its types.
3023 * \param [in] begin - an array of cell ids of interest.
3024 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3025 * \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3026 * describing the cell types.
3027 * \throw If the coordinates array is not set.
3028 * \throw If the nodal connectivity of cells is not defined.
3029 * \sa getAllGeoTypes()
3031 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3033 checkFullyDefined();
3034 std::set<INTERP_KERNEL::NormalizedCellType> ret;
3035 const int *conn=_nodal_connec->getConstPointer();
3036 const int *connIndex=_nodal_connec_index->getConstPointer();
3037 for(const int *w=begin;w!=end;w++)
3038 ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3043 * Defines the nodal connectivity using given connectivity arrays. Optionally updates
3044 * a set of types of cells constituting \a this mesh.
3045 * This method is for advanced users having prepared their connectivity before. For
3046 * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3047 * \param [in] conn - the nodal connectivity array.
3048 * \param [in] connIndex - the nodal connectivity index array.
3049 * \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3052 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3054 DataArrayInt::SetArrayIn(conn,_nodal_connec);
3055 DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3056 if(isComputingTypes)
3062 * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
3063 * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3065 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3066 _nodal_connec(0),_nodal_connec_index(0),
3067 _types(other._types)
3069 if(other._nodal_connec)
3070 _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3071 if(other._nodal_connec_index)
3072 _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3075 MEDCouplingUMesh::~MEDCouplingUMesh()
3078 _nodal_connec->decrRef();
3079 if(_nodal_connec_index)
3080 _nodal_connec_index->decrRef();
3084 * Recomputes a set of cell types of \a this mesh. For more info see
3085 * \ref MEDCouplingUMeshNodalConnectivity.
3087 void MEDCouplingUMesh::computeTypes()
3089 if(_nodal_connec && _nodal_connec_index)
3092 const int *conn=_nodal_connec->getConstPointer();
3093 const int *connIndex=_nodal_connec_index->getConstPointer();
3094 int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
3096 for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
3097 _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
3102 * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3104 void MEDCouplingUMesh::checkFullyDefined() const
3106 if(!_nodal_connec_index || !_nodal_connec || !_coords)
3107 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3111 * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3113 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3115 if(!_nodal_connec_index || !_nodal_connec)
3116 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3120 * Returns a number of cells constituting \a this mesh.
3121 * \return int - the number of cells in \a this mesh.
3122 * \throw If the nodal connectivity of cells is not defined.
3124 int MEDCouplingUMesh::getNumberOfCells() const
3126 if(_nodal_connec_index)
3127 return _nodal_connec_index->getNumberOfTuples()-1;
3132 throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3136 * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3137 * mesh. For more info see \ref MEDCouplingMeshesPage.
3138 * \return int - the dimension of \a this mesh.
3139 * \throw If the mesh dimension is not defined using setMeshDimension().
3141 int MEDCouplingUMesh::getMeshDimension() const
3144 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3149 * Returns a length of the nodal connectivity array.
3150 * This method is for test reason. Normally the integer returned is not useable by
3151 * user. For more info see \ref MEDCouplingUMeshNodalConnectivity.
3152 * \return int - the length of the nodal connectivity array.
3154 int MEDCouplingUMesh::getMeshLength() const
3156 return _nodal_connec->getNbOfElems();
3160 * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3162 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3164 MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3165 tinyInfo.push_back(getMeshDimension());
3166 tinyInfo.push_back(getNumberOfCells());
3168 tinyInfo.push_back(getMeshLength());
3170 tinyInfo.push_back(-1);
3174 * First step of unserialization process.
3176 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3178 return tinyInfo[6]<=0;
3182 * Second step of serialization process.
3183 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3185 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3187 MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3189 a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3193 * Third and final step of serialization process.
3195 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3197 MEDCouplingPointSet::serialize(a1,a2);
3198 if(getMeshDimension()>-1)
3200 a1=DataArrayInt::New();
3201 a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3202 int *ptA1=a1->getPointer();
3203 const int *conn=getNodalConnectivity()->getConstPointer();
3204 const int *index=getNodalConnectivityIndex()->getConstPointer();
3205 ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3206 std::copy(conn,conn+getMeshLength(),ptA1);
3213 * Second and final unserialization process.
3214 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3216 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3218 MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3219 setMeshDimension(tinyInfo[5]);
3223 const int *recvBuffer=a1->getConstPointer();
3224 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3225 myConnecIndex->alloc(tinyInfo[6]+1,1);
3226 std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3227 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3228 myConnec->alloc(tinyInfo[7],1);
3229 std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3230 setConnectivity(myConnec, myConnecIndex);
3235 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3236 * CellIds are given using range specified by a start an end and step.
3238 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3240 checkFullyDefined();
3241 int ncell=getNumberOfCells();
3242 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3243 ret->_mesh_dim=_mesh_dim;
3244 ret->setCoords(_coords);
3245 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3246 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3247 int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3249 const int *conn=_nodal_connec->getConstPointer();
3250 const int *connIndex=_nodal_connec_index->getConstPointer();
3251 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3253 if(work>=0 && work<ncell)
3255 newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3259 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3260 throw INTERP_KERNEL::Exception(oss.str().c_str());
3263 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3264 int *newConnPtr=newConn->getPointer();
3265 std::set<INTERP_KERNEL::NormalizedCellType> types;
3267 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3269 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3270 newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3272 ret->setConnectivity(newConn,newConnI,false);
3274 ret->copyTinyInfoFrom(this);
3279 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3280 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3281 * The return newly allocated mesh will share the same coordinates as \a this.
3283 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3285 checkConnectivityFullyDefined();
3286 int ncell=getNumberOfCells();
3287 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3288 ret->_mesh_dim=_mesh_dim;
3289 ret->setCoords(_coords);
3290 std::size_t nbOfElemsRet=std::distance(begin,end);
3291 int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3293 const int *conn=_nodal_connec->getConstPointer();
3294 const int *connIndex=_nodal_connec_index->getConstPointer();
3296 for(const int *work=begin;work!=end;work++,newNbring++)
3298 if(*work>=0 && *work<ncell)
3299 connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3303 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3304 throw INTERP_KERNEL::Exception(oss.str().c_str());
3307 int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3308 int *connRetWork=connRet;
3309 std::set<INTERP_KERNEL::NormalizedCellType> types;
3310 for(const int *work=begin;work!=end;work++)
3312 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3313 connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3315 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3316 connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3317 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3318 connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3319 ret->setConnectivity(connRetArr,connIndexRetArr,false);
3321 ret->copyTinyInfoFrom(this);
3326 * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3328 * For 1D cells, the returned field contains lengths.<br>
3329 * For 2D cells, the returned field contains areas.<br>
3330 * For 3D cells, the returned field contains volumes.
3331 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3332 * orientation, i.e. the volume is always positive.
3333 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3334 * and one time . The caller is to delete this field using decrRef() as it is no
3337 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3339 std::string name="MeasureOfMesh_";
3341 int nbelem=getNumberOfCells();
3342 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3343 field->setName(name);
3344 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3345 array->alloc(nbelem,1);
3346 double *area_vol=array->getPointer();
3347 field->setArray(array) ; array=0;
3348 field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3349 field->synchronizeTimeWithMesh();
3350 if(getMeshDimension()!=-1)
3353 INTERP_KERNEL::NormalizedCellType type;
3354 int dim_space=getSpaceDimension();
3355 const double *coords=getCoords()->getConstPointer();
3356 const int *connec=getNodalConnectivity()->getConstPointer();
3357 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3358 for(int iel=0;iel<nbelem;iel++)
3360 ipt=connec_index[iel];
3361 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3362 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);
3365 std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3369 area_vol[0]=std::numeric_limits<double>::max();
3371 return field.retn();
3375 * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3377 * For 1D cells, the returned array contains lengths.<br>
3378 * For 2D cells, the returned array contains areas.<br>
3379 * For 3D cells, the returned array contains volumes.
3380 * This method avoids building explicitly a part of \a this mesh to perform the work.
3381 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3382 * orientation, i.e. the volume is always positive.
3383 * \param [in] begin - an array of cell ids of interest.
3384 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3385 * \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3386 * delete this array using decrRef() as it is no more needed.
3388 * \if ENABLE_EXAMPLES
3389 * \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3390 * \ref py_mcumesh_getPartMeasureField "Here is a Python example".
3392 * \sa getMeasureField()
3394 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3396 std::string name="PartMeasureOfMesh_";
3398 int nbelem=(int)std::distance(begin,end);
3399 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3400 array->setName(name);
3401 array->alloc(nbelem,1);
3402 double *area_vol=array->getPointer();
3403 if(getMeshDimension()!=-1)
3406 INTERP_KERNEL::NormalizedCellType type;
3407 int dim_space=getSpaceDimension();
3408 const double *coords=getCoords()->getConstPointer();
3409 const int *connec=getNodalConnectivity()->getConstPointer();
3410 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3411 for(const int *iel=begin;iel!=end;iel++)
3413 ipt=connec_index[*iel];
3414 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3415 *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3418 std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3422 area_vol[0]=std::numeric_limits<double>::max();
3424 return array.retn();
3428 * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3429 * \a this one. The returned field contains the dual cell volume for each corresponding
3430 * node in \a this mesh. In other words, the field returns the getMeasureField() of
3431 * the dual mesh in P1 sens of \a this.<br>
3432 * For 1D cells, the returned field contains lengths.<br>
3433 * For 2D cells, the returned field contains areas.<br>
3434 * For 3D cells, the returned field contains volumes.
3435 * This method is useful to check "P1*" conservative interpolators.
3436 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3437 * orientation, i.e. the volume is always positive.
3438 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3439 * nodes and one time. The caller is to delete this array using decrRef() as
3440 * it is no more needed.
3442 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3444 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3445 std::string name="MeasureOnNodeOfMesh_";
3447 int nbNodes=getNumberOfNodes();
3448 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3449 double cst=1./((double)getMeshDimension()+1.);
3450 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3451 array->alloc(nbNodes,1);
3452 double *valsToFill=array->getPointer();
3453 std::fill(valsToFill,valsToFill+nbNodes,0.);
3454 const double *values=tmp->getArray()->getConstPointer();
3455 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3456 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3457 getReverseNodalConnectivity(da,daInd);
3458 const int *daPtr=da->getConstPointer();
3459 const int *daIPtr=daInd->getConstPointer();
3460 for(int i=0;i<nbNodes;i++)
3461 for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3462 valsToFill[i]+=cst*values[*cell];
3464 ret->setArray(array);
3469 * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3470 * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3471 * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3472 * and are normalized.
3473 * <br> \a this can be either
3474 * - a 2D mesh in 2D or 3D space or
3475 * - an 1D mesh in 2D space.
3477 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3478 * cells and one time. The caller is to delete this field using decrRef() as
3479 * it is no more needed.
3480 * \throw If the nodal connectivity of cells is not defined.
3481 * \throw If the coordinates array is not set.
3482 * \throw If the mesh dimension is not set.
3483 * \throw If the mesh and space dimension is not as specified above.
3485 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3487 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3488 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3489 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3490 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3491 int nbOfCells=getNumberOfCells();
3492 int nbComp=getMeshDimension()+1;
3493 array->alloc(nbOfCells,nbComp);
3494 double *vals=array->getPointer();
3495 const int *connI=_nodal_connec_index->getConstPointer();
3496 const int *conn=_nodal_connec->getConstPointer();
3497 const double *coords=_coords->getConstPointer();
3498 if(getMeshDimension()==2)
3500 if(getSpaceDimension()==3)
3502 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3503 const double *locPtr=loc->getConstPointer();
3504 for(int i=0;i<nbOfCells;i++,vals+=3)
3506 int offset=connI[i];
3507 INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3508 double n=INTERP_KERNEL::norm<3>(vals);
3509 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3514 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3515 const double *isAbsPtr=isAbs->getArray()->begin();
3516 for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3517 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3520 else//meshdimension==1
3523 for(int i=0;i<nbOfCells;i++)
3525 int offset=connI[i];
3526 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3527 double n=INTERP_KERNEL::norm<2>(tmp);
3528 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3533 ret->setArray(array);
3535 ret->synchronizeTimeWithSupport();
3540 * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3541 * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3542 * and are normalized.
3543 * <br> \a this can be either
3544 * - a 2D mesh in 2D or 3D space or
3545 * - an 1D mesh in 2D space.
3547 * This method avoids building explicitly a part of \a this mesh to perform the work.
3548 * \param [in] begin - an array of cell ids of interest.
3549 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3550 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3551 * cells and one time. The caller is to delete this field using decrRef() as
3552 * it is no more needed.
3553 * \throw If the nodal connectivity of cells is not defined.
3554 * \throw If the coordinates array is not set.
3555 * \throw If the mesh dimension is not set.
3556 * \throw If the mesh and space dimension is not as specified above.
3557 * \sa buildOrthogonalField()
3559 * \if ENABLE_EXAMPLES
3560 * \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3561 * \ref py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3564 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3566 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3567 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3568 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3569 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3570 std::size_t nbelems=std::distance(begin,end);
3571 int nbComp=getMeshDimension()+1;
3572 array->alloc((int)nbelems,nbComp);
3573 double *vals=array->getPointer();
3574 const int *connI=_nodal_connec_index->getConstPointer();
3575 const int *conn=_nodal_connec->getConstPointer();
3576 const double *coords=_coords->getConstPointer();
3577 if(getMeshDimension()==2)
3579 if(getSpaceDimension()==3)
3581 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3582 const double *locPtr=loc->getConstPointer();
3583 for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3585 int offset=connI[*i];
3586 INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3587 double n=INTERP_KERNEL::norm<3>(vals);
3588 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3593 for(std::size_t i=0;i<nbelems;i++)
3594 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3597 else//meshdimension==1
3600 for(const int *i=begin;i!=end;i++)
3602 int offset=connI[*i];
3603 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3604 double n=INTERP_KERNEL::norm<2>(tmp);
3605 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3610 ret->setArray(array);
3612 ret->synchronizeTimeWithSupport();
3617 * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3618 * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3619 * and are \b not normalized.
3620 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3621 * cells and one time. The caller is to delete this field using decrRef() as
3622 * it is no more needed.
3623 * \throw If the nodal connectivity of cells is not defined.
3624 * \throw If the coordinates array is not set.
3625 * \throw If \a this->getMeshDimension() != 1.
3626 * \throw If \a this mesh includes cells of type other than SEG2.
3628 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3630 if(getMeshDimension()!=1)
3631 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3632 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3633 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3634 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3635 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3636 int nbOfCells=getNumberOfCells();
3637 int spaceDim=getSpaceDimension();
3638 array->alloc(nbOfCells,spaceDim);
3639 double *pt=array->getPointer();
3640 const double *coo=getCoords()->getConstPointer();
3641 std::vector<int> conn;
3643 for(int i=0;i<nbOfCells;i++)
3646 getNodeIdsOfCell(i,conn);
3647 pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3649 ret->setArray(array);
3651 ret->synchronizeTimeWithSupport();
3656 * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3657 * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3658 * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3659 * from. If a result face is shared by two 3D cells, then the face in included twice in
3661 * \param [in] origin - 3 components of a point defining location of the plane.
3662 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3663 * must be greater than 1e-6.
3664 * \param [in] eps - half-thickness of the plane.
3665 * \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3666 * producing correspondent 2D cells. The caller is to delete this array
3667 * using decrRef() as it is no more needed.
3668 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3669 * not share the node coordinates array with \a this mesh. The caller is to
3670 * delete this mesh using decrRef() as it is no more needed.
3671 * \throw If the coordinates array is not set.
3672 * \throw If the nodal connectivity of cells is not defined.
3673 * \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3674 * \throw If magnitude of \a vec is less than 1e-6.
3675 * \throw If the plane does not intersect any 3D cell of \a this mesh.
3676 * \throw If \a this includes quadratic cells.
3678 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3680 checkFullyDefined();
3681 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3682 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3683 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3684 if(candidates->empty())
3685 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3686 std::vector<int> nodes;
3687 DataArrayInt *cellIds1D=0;
3688 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3689 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3690 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3691 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3692 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3693 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3694 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3695 revDesc2=0; revDescIndx2=0;
3696 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3697 revDesc1=0; revDescIndx1=0;
3698 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3699 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3701 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3702 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3704 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3705 std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3706 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3707 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3708 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3709 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3710 connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3711 subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3712 if(cellIds2->empty())
3713 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3714 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3715 ret->setCoords(mDesc1->getCoords());
3716 ret->setConnectivity(conn,connI,true);
3717 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3722 * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3723 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
3724 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3726 * \param [in] origin - 3 components of a point defining location of the plane.
3727 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3728 * must be greater than 1e-6.
3729 * \param [in] eps - half-thickness of the plane.
3730 * \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3731 * producing correspondent segments. The caller is to delete this array
3732 * using decrRef() as it is no more needed.
3733 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3734 * mesh in 3D space. This mesh does not share the node coordinates array with
3735 * \a this mesh. The caller is to delete this mesh using decrRef() as it is
3737 * \throw If the coordinates array is not set.
3738 * \throw If the nodal connectivity of cells is not defined.
3739 * \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3740 * \throw If magnitude of \a vec is less than 1e-6.
3741 * \throw If the plane does not intersect any 2D cell of \a this mesh.
3742 * \throw If \a this includes quadratic cells.
3744 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3746 checkFullyDefined();
3747 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3748 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3749 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3750 if(candidates->empty())
3751 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3752 std::vector<int> nodes;
3753 DataArrayInt *cellIds1D=0;
3754 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3755 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3756 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3757 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3758 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3759 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3760 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3761 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3762 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3764 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3765 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3767 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3768 int ncellsSub=subMesh->getNumberOfCells();
3769 std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3770 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3771 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3772 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3773 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3775 const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3776 const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3777 for(int i=0;i<ncellsSub;i++)
3779 if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3781 if(cut3DSurf[i].first!=-2)
3783 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3784 connI->pushBackSilent(conn->getNumberOfTuples());
3785 cellIds2->pushBackSilent(i);
3789 int cellId3DSurf=cut3DSurf[i].second;
3790 int offset=nodalI[cellId3DSurf]+1;
3791 int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3792 for(int j=0;j<nbOfEdges;j++)
3794 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3795 connI->pushBackSilent(conn->getNumberOfTuples());
3796 cellIds2->pushBackSilent(cellId3DSurf);
3801 if(cellIds2->empty())
3802 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3803 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3804 ret->setCoords(mDesc1->getCoords());
3805 ret->setConnectivity(conn,connI,true);
3806 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3811 * Finds cells whose bounding boxes intersect a given plane.
3812 * \param [in] origin - 3 components of a point defining location of the plane.
3813 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3814 * must be greater than 1e-6.
3815 * \param [in] eps - half-thickness of the plane.
3816 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3817 * cells. The caller is to delete this array using decrRef() as it is no more
3819 * \throw If the coordinates array is not set.
3820 * \throw If the nodal connectivity of cells is not defined.
3821 * \throw If \a this->getSpaceDimension() != 3.
3822 * \throw If magnitude of \a vec is less than 1e-6.
3823 * \sa buildSlice3D()
3825 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3827 checkFullyDefined();
3828 if(getSpaceDimension()!=3)
3829 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3830 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3832 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3834 vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3835 double angle=acos(vec[2]/normm);
3836 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3840 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3841 MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3842 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3844 mw->getBoundingBox(bbox);
3845 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3846 cellIds=mw->getCellsInBoundingBox(bbox,eps);
3850 getBoundingBox(bbox);
3851 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3852 cellIds=getCellsInBoundingBox(bbox,eps);
3854 return cellIds.retn();
3858 * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3859 * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3860 * No consideration of coordinate is done by this method.
3861 * 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)
3862 * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3864 bool MEDCouplingUMesh::isContiguous1D() const
3866 if(getMeshDimension()!=1)
3867 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3868 int nbCells=getNumberOfCells();
3870 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3871 const int *connI=_nodal_connec_index->getConstPointer();
3872 const int *conn=_nodal_connec->getConstPointer();
3873 int ref=conn[connI[0]+2];
3874 for(int i=1;i<nbCells;i++)
3876 if(conn[connI[i]+1]!=ref)
3878 ref=conn[connI[i]+2];
3884 * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3885 * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3886 * \param pt reference point of the line
3887 * \param v normalized director vector of the line
3888 * \param eps max precision before throwing an exception
3889 * \param res output of size this->getNumberOfCells
3891 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3893 if(getMeshDimension()!=1)
3894 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3895 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3896 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3897 if(getSpaceDimension()!=3)
3898 throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3899 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3900 const double *fPtr=f->getArray()->getConstPointer();
3902 for(int i=0;i<getNumberOfCells();i++)
3904 const double *tmp1=fPtr+3*i;
3905 tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3906 tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3907 tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3908 double n1=INTERP_KERNEL::norm<3>(tmp);
3909 n1/=INTERP_KERNEL::norm<3>(tmp1);
3911 throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3913 const double *coo=getCoords()->getConstPointer();
3914 for(int i=0;i<getNumberOfNodes();i++)
3916 std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3917 std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3918 res[i]=std::accumulate(tmp,tmp+3,0.);
3923 * 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.
3924 * \a this is expected to be a mesh so that its space dimension is equal to its
3925 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3926 * 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).
3928 * 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
3929 * 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).
3930 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3932 * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3933 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3935 * \param [in] ptBg the start pointer (included) of the coordinates of the point
3936 * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3937 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3938 * \return the positive value of the distance.
3939 * \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
3941 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3943 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
3945 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3946 if(meshDim!=spaceDim-1)
3947 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3948 if(meshDim!=2 && meshDim!=1)
3949 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3950 checkFullyDefined();
3951 if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3952 { 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()); }
3953 DataArrayInt *ret1=0;
3954 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
3955 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
3956 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
3957 cellId=*ret1Safe->begin();
3958 return *ret0->begin();
3962 * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
3963 * to \a this and the first \a cellId in \a this corresponding to the returned distance.
3964 * 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
3965 * 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).
3966 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3968 * \a this is expected to be a mesh so that its space dimension is equal to its
3969 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3970 * 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).
3972 * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
3973 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3975 * \param [in] pts the list of points in which each tuple represents a point
3976 * \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.
3977 * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
3978 * \throw if number of components of \a pts is not equal to the space dimension.
3979 * \throw if mesh dimension of \a this is not equal to space dimension - 1.
3980 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
3982 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
3985 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
3986 pts->checkAllocated();
3987 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3988 if(meshDim!=spaceDim-1)
3989 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
3990 if(meshDim!=2 && meshDim!=1)
3991 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
3992 if(pts->getNumberOfComponents()!=spaceDim)
3994 std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
3995 throw INTERP_KERNEL::Exception(oss.str().c_str());
3997 checkFullyDefined();
3998 int nbCells=getNumberOfCells();
4000 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4001 int nbOfPts=pts->getNumberOfTuples();
4002 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4003 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4004 const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4005 double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4006 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4007 const double *bbox(bboxArr->begin());
4012 BBTreeDst<3> myTree(bbox,0,0,nbCells);
4013 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4015 double x=std::numeric_limits<double>::max();
4016 std::vector<int> elems;
4017 myTree.getMinDistanceOfMax(ptsPtr,x);
4018 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4019 DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4025 BBTreeDst<2> myTree(bbox,0,0,nbCells);
4026 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4028 double x=std::numeric_limits<double>::max();
4029 std::vector<int> elems;
4030 myTree.getMinDistanceOfMax(ptsPtr,x);
4031 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4032 DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4037 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4039 cellIds=ret1.retn();
4044 * \param [in] pt the start pointer (included) of the coordinates of the point
4045 * \param [in] cellIdsBg the start pointer (included) of cellIds
4046 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4047 * \param [in] nc nodal connectivity
4048 * \param [in] ncI nodal connectivity index
4049 * \param [in,out] ret0 the min distance between \a this and the external input point
4050 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4051 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4053 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)
4056 ret0=std::numeric_limits<double>::max();
4057 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4059 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4061 case INTERP_KERNEL::NORM_TRI3:
4063 double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4065 { ret0=tmp; cellId=*zeCell; }
4068 case INTERP_KERNEL::NORM_QUAD4:
4069 case INTERP_KERNEL::NORM_POLYGON:
4071 double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4073 { ret0=tmp; cellId=*zeCell; }
4077 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4083 * \param [in] pt the start pointer (included) of the coordinates of the point
4084 * \param [in] cellIdsBg the start pointer (included) of cellIds
4085 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4086 * \param [in] nc nodal connectivity
4087 * \param [in] ncI nodal connectivity index
4088 * \param [in,out] ret0 the min distance between \a this and the external input point
4089 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4090 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4092 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)
4095 ret0=std::numeric_limits<double>::max();
4096 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4098 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4100 case INTERP_KERNEL::NORM_SEG2:
4102 std::size_t uselessEntry=0;
4103 double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4106 { ret0=tmp; cellId=*zeCell; }
4110 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4116 * Finds cells in contact with a ball (i.e. a point with precision).
4117 * 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.
4118 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4120 * \warning This method is suitable if the caller intends to evaluate only one
4121 * point, for more points getCellsContainingPoints() is recommended as it is
4123 * \param [in] pos - array of coordinates of the ball central point.
4124 * \param [in] eps - ball radius.
4125 * \return int - a smallest id of cells being in contact with the ball, -1 in case
4126 * if there are no such cells.
4127 * \throw If the coordinates array is not set.
4128 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4130 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4132 std::vector<int> elts;
4133 getCellsContainingPoint(pos,eps,elts);
4136 return elts.front();
4140 * Finds cells in contact with a ball (i.e. a point with precision).
4141 * 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.
4142 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4143 * \warning This method is suitable if the caller intends to evaluate only one
4144 * point, for more points getCellsContainingPoints() is recommended as it is
4146 * \param [in] pos - array of coordinates of the ball central point.
4147 * \param [in] eps - ball radius.
4148 * \param [out] elts - vector returning ids of the found cells. It is cleared
4149 * before inserting ids.
4150 * \throw If the coordinates array is not set.
4151 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4153 * \if ENABLE_EXAMPLES
4154 * \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4155 * \ref py_mcumesh_getCellsContainingPoint "Here is a Python example".
4158 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4160 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4161 getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4162 elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4167 namespace ParaMEDMEM
4169 template<const int SPACEDIMM>
4173 static const int MY_SPACEDIM=SPACEDIMM;
4174 static const int MY_MESHDIM=8;
4175 typedef int MyConnType;
4176 static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4178 // useless, but for windows compilation ...
4179 const double* getCoordinatesPtr() const { return 0; }
4180 const int* getConnectivityPtr() const { return 0; }
4181 const int* getConnectivityIndexPtr() const { return 0; }
4182 INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4189 * Warning the nodes in \a m should be decrRefed ! To avoid that Node * pointer be replaced by another instance.
4191 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m)
4193 INTERP_KERNEL::Edge *ret(0);
4194 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]));
4195 m[n0]=bg[0]; m[n1]=bg[1];
4198 case INTERP_KERNEL::NORM_SEG2:
4200 ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4203 case INTERP_KERNEL::NORM_SEG3:
4205 INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4206 INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4207 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4208 // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4209 bool colinearity(inters.areColinears());
4210 delete e1; delete e2;
4212 { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4214 { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4218 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4223 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4225 INTERP_KERNEL::Edge *ret=0;
4228 case INTERP_KERNEL::NORM_SEG2:
4230 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4233 case INTERP_KERNEL::NORM_SEG3:
4235 INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4236 INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4237 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4238 // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4239 bool colinearity=inters.areColinears();
4240 delete e1; delete e2;
4242 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4244 ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4245 mapp2[bg[2]].second=false;
4249 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4255 * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4256 * the global mesh 'mDesc'.
4257 * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4258 * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4260 INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4261 std::map<INTERP_KERNEL::Node *,int>& mapp)
4264 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.
4265 const double *coo=mDesc->getCoords()->getConstPointer();
4266 const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4267 const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4269 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4270 s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4271 for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4273 INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4274 mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4276 INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4277 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4279 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4280 ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4282 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4284 if((*it2).second.second)
4285 mapp[(*it2).second.first]=(*it2).first;
4286 ((*it2).second.first)->decrRef();
4291 INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4295 int locId=nodeId-offset2;
4296 return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4300 int locId=nodeId-offset1;
4301 return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4303 return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4307 * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4309 void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4310 const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4311 /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4313 for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4315 int eltId1=abs(*desc1)-1;
4316 for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4318 std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4319 if(it==mappRev.end())
4321 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4332 template<int SPACEDIM>
4333 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4334 double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4336 elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4337 int *eltsIndexPtr(eltsIndex->getPointer());
4338 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4339 const double *bbox(bboxArr->begin());
4340 int nbOfCells=getNumberOfCells();
4341 const int *conn=_nodal_connec->getConstPointer();
4342 const int *connI=_nodal_connec_index->getConstPointer();
4343 double bb[2*SPACEDIM];
4344 BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4345 for(int i=0;i<nbOfPoints;i++)
4347 eltsIndexPtr[i+1]=eltsIndexPtr[i];
4348 for(int j=0;j<SPACEDIM;j++)
4350 bb[2*j]=pos[SPACEDIM*i+j];
4351 bb[2*j+1]=pos[SPACEDIM*i+j];
4353 std::vector<int> candidates;
4354 myTree.getIntersectingElems(bb,candidates);
4355 for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4357 int sz(connI[(*iter)+1]-connI[*iter]-1);
4358 INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4360 if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4361 status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4365 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4366 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4367 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4368 std::vector<INTERP_KERNEL::Node *> nodes(sz);
4369 INTERP_KERNEL::QuadraticPolygon *pol(0);
4370 for(int j=0;j<sz;j++)
4372 int nodeId(conn[connI[*iter]+1+j]);
4373 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4375 if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4376 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4378 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4379 INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4380 double a(0.),b(0.),c(0.);
4381 a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4382 status=pol->isInOrOut2(n);
4383 delete pol; n->decrRef();
4387 eltsIndexPtr[i+1]++;
4388 elts->pushBackSilent(*iter);
4394 * Finds cells in contact with several balls (i.e. points with precision).
4395 * This method is an extension of getCellContainingPoint() and
4396 * getCellsContainingPoint() for the case of multiple points.
4397 * 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.
4398 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4399 * \param [in] pos - an array of coordinates of points in full interlace mode :
4400 * X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4401 * this->getSpaceDimension() * \a nbOfPoints
4402 * \param [in] nbOfPoints - number of points to locate within \a this mesh.
4403 * \param [in] eps - radius of balls (i.e. the precision).
4404 * \param [out] elts - vector returning ids of found cells.
4405 * \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4406 * dividing cell ids in \a elts into groups each referring to one
4407 * point. Its every element (except the last one) is an index pointing to the
4408 * first id of a group of cells. For example cells in contact with the *i*-th
4409 * point are described by following range of indices:
4410 * [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4411 * \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4412 * Number of cells in contact with the *i*-th point is
4413 * \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4414 * \throw If the coordinates array is not set.
4415 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4417 * \if ENABLE_EXAMPLES
4418 * \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4419 * \ref py_mcumesh_getCellsContainingPoints "Here is a Python example".
4422 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4423 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4425 int spaceDim=getSpaceDimension();
4426 int mDim=getMeshDimension();
4431 const double *coords=_coords->getConstPointer();
4432 getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4439 throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4441 else if(spaceDim==2)
4445 const double *coords=_coords->getConstPointer();
4446 getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4449 throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4451 else if(spaceDim==1)
4455 const double *coords=_coords->getConstPointer();
4456 getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4459 throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4462 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4466 * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4467 * least two its edges intersect each other anywhere except their extremities. An
4468 * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4469 * \param [in,out] cells - a vector returning ids of the found cells. It is not
4470 * cleared before filling in.
4471 * \param [in] eps - precision.
4472 * \throw If \a this->getMeshDimension() != 2.
4473 * \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4475 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4477 const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4478 if(getMeshDimension()!=2)
4479 throw INTERP_KERNEL::Exception(msg);
4480 int spaceDim=getSpaceDimension();
4481 if(spaceDim!=2 && spaceDim!=3)
4482 throw INTERP_KERNEL::Exception(msg);
4483 const int *conn=_nodal_connec->getConstPointer();
4484 const int *connI=_nodal_connec_index->getConstPointer();
4485 int nbOfCells=getNumberOfCells();
4486 std::vector<double> cell2DinS2;
4487 for(int i=0;i<nbOfCells;i++)
4489 int offset=connI[i];
4490 int nbOfNodesForCell=connI[i+1]-offset-1;
4491 if(nbOfNodesForCell<=3)
4493 bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4494 project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4495 if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4502 * This method is typically requested to unbutterfly 2D linear cells in \b this.
4504 * 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.
4505 * 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.
4507 * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4508 * This convex envelop is computed using Jarvis march algorithm.
4509 * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4510 * 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)
4511 * 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.
4513 * \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.
4514 * \sa MEDCouplingUMesh::colinearize2D
4516 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4518 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4519 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D works only for meshDim=2 and spaceDim=2 !");
4520 checkFullyDefined();
4521 const double *coords=getCoords()->getConstPointer();
4522 int nbOfCells=getNumberOfCells();
4523 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4524 nodalConnecIndexOut->alloc(nbOfCells+1,1);
4525 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4526 int *workIndexOut=nodalConnecIndexOut->getPointer();
4528 const int *nodalConnecIn=_nodal_connec->getConstPointer();
4529 const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4530 std::set<INTERP_KERNEL::NormalizedCellType> types;
4531 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4532 isChanged->alloc(0,1);
4533 for(int i=0;i<nbOfCells;i++,workIndexOut++)
4535 int pos=nodalConnecOut->getNumberOfTuples();
4536 if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4537 isChanged->pushBackSilent(i);
4538 types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4539 workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4541 if(isChanged->empty())
4543 setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4545 return isChanged.retn();
4549 * This method is \b NOT const because it can modify \a this.
4550 * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4551 * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4552 * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4553 * \b 1 for translation and rotation around point of 'mesh1D'.
4554 * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.
4556 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4558 checkFullyDefined();
4559 mesh1D->checkFullyDefined();
4560 if(!mesh1D->isContiguous1D())
4561 throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4562 if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4563 throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4564 if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4565 throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4566 if(mesh1D->getMeshDimension()!=1)
4567 throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4569 if(isPresenceOfQuadratic())
4571 if(mesh1D->isFullyQuadratic())
4574 throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4577 int oldNbOfNodes=getNumberOfNodes();
4578 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4583 newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4588 newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4592 throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4594 setCoords(newCoords);
4595 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4601 * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4602 * If it is not the case an exception will be thrown.
4603 * This method is non const because the coordinate of \a this can be appended with some new points issued from
4604 * intersection of plane defined by ('origin','vec').
4605 * This method has one in/out parameter : 'cut3DCurve'.
4606 * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4607 * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4608 * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4609 * This method will throw an exception if \a this contains a non linear segment.
4611 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4613 checkFullyDefined();
4614 if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4615 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4616 int ncells=getNumberOfCells();
4617 int nnodes=getNumberOfNodes();
4618 double vec2[3],vec3[3],vec4[3];
4619 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4621 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4622 vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4623 const int *conn=_nodal_connec->getConstPointer();
4624 const int *connI=_nodal_connec_index->getConstPointer();
4625 const double *coo=_coords->getConstPointer();
4626 std::vector<double> addCoo;
4627 for(int i=0;i<ncells;i++)
4629 if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4631 if(cut3DCurve[i]==-2)
4633 int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4634 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];
4635 double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4636 double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4637 if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4639 const double *st2=coo+3*st;
4640 vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4641 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]));
4642 if(pos>eps && pos<1-eps)
4644 int nNode=((int)addCoo.size())/3;
4645 vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4646 addCoo.insert(addCoo.end(),vec4,vec4+3);
4647 cut3DCurve[i]=nnodes+nNode;
4653 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4657 int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4658 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4659 coo2->alloc(newNbOfNodes,3);
4660 double *tmp=coo2->getPointer();
4661 tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4662 std::copy(addCoo.begin(),addCoo.end(),tmp);
4663 DataArrayDouble::SetArrayIn(coo2,_coords);
4668 * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4669 * \param mesh1D is the input 1D mesh used for translation computation.
4670 * \return newCoords new coords filled by this method.
4672 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4674 int oldNbOfNodes=getNumberOfNodes();
4675 int nbOf1DCells=mesh1D->getNumberOfCells();
4676 int spaceDim=getSpaceDimension();
4677 DataArrayDouble *ret=DataArrayDouble::New();
4678 std::vector<bool> isQuads;
4679 int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4680 ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4681 double *retPtr=ret->getPointer();
4682 const double *coords=getCoords()->getConstPointer();
4683 double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4685 std::vector<double> c;
4689 for(int i=0;i<nbOf1DCells;i++)
4692 mesh1D->getNodeIdsOfCell(i,v);
4694 mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4695 mesh1D->getCoordinatesOfNode(v[0],c);
4696 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4697 for(int j=0;j<oldNbOfNodes;j++)
4698 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4702 mesh1D->getCoordinatesOfNode(v[1],c);
4703 mesh1D->getCoordinatesOfNode(v[0],c);
4704 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4705 for(int j=0;j<oldNbOfNodes;j++)
4706 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4709 ret->copyStringInfoFrom(*getCoords());
4714 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4715 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4716 * \return newCoords new coords filled by this method.
4718 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4720 if(mesh1D->getSpaceDimension()==2)
4721 return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4722 if(mesh1D->getSpaceDimension()==3)
4723 return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4724 throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4728 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4729 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4730 * \return newCoords new coords filled by this method.
4732 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4735 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4736 int oldNbOfNodes=getNumberOfNodes();
4737 int nbOf1DCells=mesh1D->getNumberOfCells();
4739 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4740 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4741 int nbOfLevsInVec=nbOf1DCells+1;
4742 ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4743 double *retPtr=ret->getPointer();
4744 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4745 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4746 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4747 tmp->setCoords(tmp2);
4748 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4749 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4750 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4751 for(int i=1;i<nbOfLevsInVec;i++)
4753 const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4754 const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4755 const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4756 const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4757 tmp->translate(vec);
4758 double tmp3[2],radius,alpha,alpha0;
4759 const double *p0=i+1<nbOfLevsInVec?begin:third;
4760 const double *p1=i+1<nbOfLevsInVec?end:begin;
4761 const double *p2=i+1<nbOfLevsInVec?third:end;
4762 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4763 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]);
4764 double angle=acos(cosangle/(radius*radius));
4765 tmp->rotate(end,0,angle);
4766 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4772 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4773 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4774 * \return newCoords new coords filled by this method.
4776 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4779 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4780 int oldNbOfNodes=getNumberOfNodes();
4781 int nbOf1DCells=mesh1D->getNumberOfCells();
4783 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4784 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4785 int nbOfLevsInVec=nbOf1DCells+1;
4786 ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4787 double *retPtr=ret->getPointer();
4788 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4789 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4790 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4791 tmp->setCoords(tmp2);
4792 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4793 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4794 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4795 for(int i=1;i<nbOfLevsInVec;i++)
4797 const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4798 const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4799 const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4800 const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4801 tmp->translate(vec);
4802 double tmp3[2],radius,alpha,alpha0;
4803 const double *p0=i+1<nbOfLevsInVec?begin:third;
4804 const double *p1=i+1<nbOfLevsInVec?end:begin;
4805 const double *p2=i+1<nbOfLevsInVec?third:end;
4806 double vecPlane[3]={
4807 (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4808 (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4809 (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4811 double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4814 vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4815 double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4816 double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4818 double c2=cos(asin(s2));
4820 {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4821 {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4822 {-vec2[1]*s2, vec2[0]*s2, c2}
4824 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]};
4825 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]};
4826 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]};
4827 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4828 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]);
4829 double angle=acos(cosangle/(radius*radius));
4830 tmp->rotate(end,vecPlane,angle);
4832 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4838 * This method is private because not easy to use for end user. This method is const contrary to
4839 * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4840 * the coords sorted slice by slice.
4841 * \param isQuad specifies presence of quadratic cells.
4843 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4845 int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4846 int nbOf2DCells=getNumberOfCells();
4847 int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4848 MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4849 const int *conn=_nodal_connec->getConstPointer();
4850 const int *connI=_nodal_connec_index->getConstPointer();
4851 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4852 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4853 newConnI->alloc(nbOf3DCells+1,1);
4854 int *newConnIPtr=newConnI->getPointer();
4856 std::vector<int> newc;
4857 for(int j=0;j<nbOf2DCells;j++)
4859 AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4860 *newConnIPtr++=(int)newc.size();
4862 newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4863 int *newConnPtr=newConn->getPointer();
4864 int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4865 newConnIPtr=newConnI->getPointer();
4866 for(int iz=0;iz<nbOf1DCells;iz++)
4869 std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4870 for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4872 int icell=(int)(iter-newc.begin());
4873 if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4876 *newConnPtr=(*iter)+iz*deltaPerLev;
4881 *newConnPtr=(*iter);
4884 ret->setConnectivity(newConn,newConnI,true);
4885 ret->setCoords(getCoords());
4890 * Checks if \a this mesh is constituted by only quadratic cells.
4891 * \return bool - \c true if there are only quadratic cells in \a this mesh.
4892 * \throw If the coordinates array is not set.
4893 * \throw If the nodal connectivity of cells is not defined.
4895 bool MEDCouplingUMesh::isFullyQuadratic() const
4897 checkFullyDefined();
4899 int nbOfCells=getNumberOfCells();
4900 for(int i=0;i<nbOfCells && ret;i++)
4902 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4903 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4904 ret=cm.isQuadratic();
4910 * Checks if \a this mesh includes any quadratic cell.
4911 * \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4912 * \throw If the coordinates array is not set.
4913 * \throw If the nodal connectivity of cells is not defined.
4915 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4917 checkFullyDefined();
4919 int nbOfCells=getNumberOfCells();
4920 for(int i=0;i<nbOfCells && !ret;i++)
4922 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4923 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4924 ret=cm.isQuadratic();
4930 * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4931 * this mesh, it remains unchanged.
4932 * \throw If the coordinates array is not set.
4933 * \throw If the nodal connectivity of cells is not defined.
4935 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4937 checkFullyDefined();
4938 int nbOfCells=getNumberOfCells();
4940 const int *iciptr=_nodal_connec_index->getConstPointer();
4941 for(int i=0;i<nbOfCells;i++)
4943 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4944 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4945 if(cm.isQuadratic())
4947 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4948 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4949 if(!cml.isDynamic())
4950 delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4952 delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4957 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4958 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4959 const int *icptr=_nodal_connec->getConstPointer();
4960 newConn->alloc(getMeshLength()-delta,1);
4961 newConnI->alloc(nbOfCells+1,1);
4962 int *ocptr=newConn->getPointer();
4963 int *ociptr=newConnI->getPointer();
4966 for(int i=0;i<nbOfCells;i++,ociptr++)
4968 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4969 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4970 if(!cm.isQuadratic())
4972 _types.insert(type);
4973 ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4974 ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4978 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4979 _types.insert(typel);
4980 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4981 int newNbOfNodes=cml.getNumberOfNodes();
4983 newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4984 *ocptr++=(int)typel;
4985 ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4986 ociptr[1]=ociptr[0]+newNbOfNodes+1;
4989 setConnectivity(newConn,newConnI,false);
4993 * This method converts all linear cell in \a this to quadratic one.
4994 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4995 * 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)
4996 * 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.
4997 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4998 * end of the existing coordinates.
5000 * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5001 * corresponding quadratic cells. 1 is those creating the 'most' complex.
5002 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5004 * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5006 * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5008 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5010 DataArrayInt *conn=0,*connI=0;
5011 DataArrayDouble *coords=0;
5012 std::set<INTERP_KERNEL::NormalizedCellType> types;
5013 checkFullyDefined();
5014 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5015 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5016 int meshDim=getMeshDimension();
5017 switch(conversionType)
5023 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5024 connSafe=conn; connISafe=connI; coordsSafe=coords;
5027 ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5028 connSafe=conn; connISafe=connI; coordsSafe=coords;
5031 ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5032 connSafe=conn; connISafe=connI; coordsSafe=coords;
5035 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5043 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5044 connSafe=conn; connISafe=connI; coordsSafe=coords;
5047 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5048 connSafe=conn; connISafe=connI; coordsSafe=coords;
5051 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5052 connSafe=conn; connISafe=connI; coordsSafe=coords;
5055 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5060 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5062 setConnectivity(connSafe,connISafe,false);
5064 setCoords(coordsSafe);
5070 * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
5071 * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
5072 * The nodes to be added in those 2D cells are defined by the pair of \a nodeIdsToAdd and \a nodeIdsIndexToAdd.
5073 * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
5074 * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
5075 * This method can be seen as the opposite method of colinearize2D.
5076 * 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
5077 * to avoid to modify the numbering of existing nodes.
5079 * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
5080 * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
5081 * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
5082 * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
5083 * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
5084 * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
5085 * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
5087 * \sa buildDescendingConnectivity2
5089 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
5090 const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
5092 if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
5093 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
5094 nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
5095 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
5096 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
5097 if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
5098 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
5099 //DataArrayInt *out0(0),*outi0(0);
5100 //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
5101 //MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s(out0),outi0s(outi0);
5102 //out0s=out0s->buildUnique(); out0s->sort(true);
5107 * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5108 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5109 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5111 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5113 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5114 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5115 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5116 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5117 int nbOfCells=getNumberOfCells();
5118 int nbOfNodes=getNumberOfNodes();
5119 const int *cPtr=_nodal_connec->getConstPointer();
5120 const int *icPtr=_nodal_connec_index->getConstPointer();
5121 int lastVal=0,offset=nbOfNodes;
5122 for(int i=0;i<nbOfCells;i++,icPtr++)
5124 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5125 if(type==INTERP_KERNEL::NORM_SEG2)
5127 types.insert(INTERP_KERNEL::NORM_SEG3);
5128 newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5129 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5130 newConn->pushBackSilent(offset++);
5132 newConnI->pushBackSilent(lastVal);
5133 ret->pushBackSilent(i);
5138 lastVal+=(icPtr[1]-icPtr[0]);
5139 newConnI->pushBackSilent(lastVal);
5140 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5143 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5144 coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5148 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
5150 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5151 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5152 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5154 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5155 DataArrayInt *conn1D=0,*conn1DI=0;
5156 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5157 DataArrayDouble *coordsTmp=0;
5158 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5159 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5160 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5161 const int *c1DPtr=conn1D->begin();
5162 const int *c1DIPtr=conn1DI->begin();
5163 int nbOfCells=getNumberOfCells();
5164 const int *cPtr=_nodal_connec->getConstPointer();
5165 const int *icPtr=_nodal_connec_index->getConstPointer();
5167 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5169 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5170 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5171 if(!cm.isQuadratic())
5173 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5174 types.insert(typ2); newConn->pushBackSilent(typ2);
5175 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5176 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5177 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5178 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5179 newConnI->pushBackSilent(lastVal);
5180 ret->pushBackSilent(i);
5185 lastVal+=(icPtr[1]-icPtr[0]);
5186 newConnI->pushBackSilent(lastVal);
5187 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5190 conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5195 * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5196 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5197 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5199 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5201 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5202 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5203 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5206 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5208 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5209 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5211 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5212 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5213 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5215 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5216 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5217 DataArrayInt *conn1D=0,*conn1DI=0;
5218 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5219 DataArrayDouble *coordsTmp=0;
5220 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5221 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5222 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5223 const int *c1DPtr=conn1D->begin();
5224 const int *c1DIPtr=conn1DI->begin();
5225 int nbOfCells=getNumberOfCells();
5226 const int *cPtr=_nodal_connec->getConstPointer();
5227 const int *icPtr=_nodal_connec_index->getConstPointer();
5228 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5229 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5231 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5232 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5233 if(!cm.isQuadratic())
5235 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5236 types.insert(typ2); newConn->pushBackSilent(typ2);
5237 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5238 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5239 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5240 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5241 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5242 newConnI->pushBackSilent(lastVal);
5243 ret->pushBackSilent(i);
5248 lastVal+=(icPtr[1]-icPtr[0]);
5249 newConnI->pushBackSilent(lastVal);
5250 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5253 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5254 coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5259 * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5260 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5261 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5263 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5265 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5266 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5267 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5270 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5272 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5273 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5274 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5275 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5277 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5278 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5279 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5281 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5282 const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5283 DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5284 std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5285 DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5286 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5287 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5288 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5289 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5290 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5291 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5292 const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5293 int nbOfCells=getNumberOfCells();
5294 const int *cPtr=_nodal_connec->getConstPointer();
5295 const int *icPtr=_nodal_connec_index->getConstPointer();
5296 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5297 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5299 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5300 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5301 if(!cm.isQuadratic())
5303 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5304 if(typ2==INTERP_KERNEL::NORM_ERROR)
5306 std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5307 throw INTERP_KERNEL::Exception(oss.str().c_str());
5309 types.insert(typ2); newConn->pushBackSilent(typ2);
5310 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5311 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5312 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5313 for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5315 int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5316 int tmpPos=newConn->getNumberOfTuples();
5317 newConn->pushBackSilent(nodeId2);
5318 ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5320 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5321 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5322 newConnI->pushBackSilent(lastVal);
5323 ret->pushBackSilent(i);
5328 lastVal+=(icPtr[1]-icPtr[0]);
5329 newConnI->pushBackSilent(lastVal);
5330 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5333 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5334 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5335 coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5336 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5337 std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5338 int *c=newConn->getPointer();
5339 const int *cI(newConnI->begin());
5340 for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5341 c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5342 offset=coordsTmp2Safe->getNumberOfTuples();
5343 for(const int *elt=ret->begin();elt!=ret->end();elt++)
5344 c[cI[(*elt)+1]-1]+=offset;
5345 coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5350 * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5351 * so that the number of cells remains the same. Quadratic faces are converted to
5352 * polygons. This method works only for 2D meshes in
5353 * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5354 * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5355 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5356 * \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5357 * a polylinized edge constituting the input polygon.
5358 * \throw If the coordinates array is not set.
5359 * \throw If the nodal connectivity of cells is not defined.
5360 * \throw If \a this->getMeshDimension() != 2.
5361 * \throw If \a this->getSpaceDimension() != 2.
5363 void MEDCouplingUMesh::tessellate2D(double eps)
5365 checkFullyDefined();
5366 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
5367 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5368 double epsa=fabs(eps);
5369 if(epsa<std::numeric_limits<double>::min())
5370 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 !");
5371 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5372 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5373 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5374 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5375 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5376 revDesc1=0; revDescIndx1=0;
5377 mDesc->tessellate2DCurve(eps);
5378 subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5379 setCoords(mDesc->getCoords());
5383 * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5384 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5385 * \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5386 * a sub-divided edge.
5387 * \throw If the coordinates array is not set.
5388 * \throw If the nodal connectivity of cells is not defined.
5389 * \throw If \a this->getMeshDimension() != 1.
5390 * \throw If \a this->getSpaceDimension() != 2.
5392 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5394 checkFullyDefined();
5395 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5396 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5397 double epsa=fabs(eps);
5398 if(epsa<std::numeric_limits<double>::min())
5399 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 !");
5400 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5401 int nbCells=getNumberOfCells();
5402 int nbNodes=getNumberOfNodes();
5403 const int *conn=_nodal_connec->getConstPointer();
5404 const int *connI=_nodal_connec_index->getConstPointer();
5405 const double *coords=_coords->getConstPointer();
5406 std::vector<double> addCoo;
5407 std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5408 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5409 newConnI->alloc(nbCells+1,1);
5410 int *newConnIPtr=newConnI->getPointer();
5413 INTERP_KERNEL::Node *tmp2[3];
5414 std::set<INTERP_KERNEL::NormalizedCellType> types;
5415 for(int i=0;i<nbCells;i++,newConnIPtr++)
5417 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5418 if(cm.isQuadratic())
5419 {//assert(connI[i+1]-connI[i]-1==3)
5420 tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5421 tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5422 tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5423 tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5424 INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5427 eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5428 types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5430 newConnIPtr[1]=(int)newConn.size();
5434 types.insert(INTERP_KERNEL::NORM_SEG2);
5435 newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5436 newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5437 newConnIPtr[1]=newConnIPtr[0]+3;
5442 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5443 newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5444 newConnIPtr[1]=newConnIPtr[0]+3;
5447 if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5450 DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5451 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5452 newConnArr->alloc((int)newConn.size(),1);
5453 std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5454 DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5455 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5456 newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5457 double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5458 std::copy(addCoo.begin(),addCoo.end(),work);
5459 DataArrayDouble::SetArrayIn(newCoords,_coords);
5464 * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5465 * In addition, returns an array mapping new cells to old ones. <br>
5466 * This method typically increases the number of cells in \a this mesh
5467 * but the number of nodes remains \b unchanged.
5468 * That's why the 3D splitting policies
5469 * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5470 * \param [in] policy - specifies a pattern used for splitting.
5471 * The semantic of \a policy is:
5472 * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5473 * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5474 * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8 into 5 TETRA4 (for 3D mesh only).
5475 * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8 into 6 TETRA4 (for 3D mesh only).
5476 * \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5477 * an id of old cell producing it. The caller is to delete this array using
5478 * decrRef() as it is no more needed.
5479 * \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5480 * \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5481 * and \a this->getMeshDimension() != 3.
5482 * \throw If \a policy is not one of the four discussed above.
5483 * \throw If the nodal connectivity of cells is not defined.
5484 * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5486 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5491 return simplexizePol0();
5493 return simplexizePol1();
5494 case (int) INTERP_KERNEL::PLANAR_FACE_5:
5495 return simplexizePlanarFace5();
5496 case (int) INTERP_KERNEL::PLANAR_FACE_6:
5497 return simplexizePlanarFace6();
5499 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)");
5504 * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5505 * - 1D: INTERP_KERNEL::NORM_SEG2
5506 * - 2D: INTERP_KERNEL::NORM_TRI3
5507 * - 3D: INTERP_KERNEL::NORM_TETRA4.
5509 * This method is useful for users that need to use P1 field services as
5510 * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5511 * All these methods need mesh support containing only simplex cells.
5512 * \return bool - \c true if there are only simplex cells in \a this mesh.
5513 * \throw If the coordinates array is not set.
5514 * \throw If the nodal connectivity of cells is not defined.
5515 * \throw If \a this->getMeshDimension() < 1.
5517 bool MEDCouplingUMesh::areOnlySimplexCells() const
5519 checkFullyDefined();
5520 int mdim=getMeshDimension();
5521 if(mdim<1 || mdim>3)
5522 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5523 int nbCells=getNumberOfCells();
5524 const int *conn=_nodal_connec->getConstPointer();
5525 const int *connI=_nodal_connec_index->getConstPointer();
5526 for(int i=0;i<nbCells;i++)
5528 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5536 * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5538 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5540 checkConnectivityFullyDefined();
5541 if(getMeshDimension()!=2)
5542 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5543 int nbOfCells=getNumberOfCells();
5544 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5545 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5546 ret->alloc(nbOfCells+nbOfCutCells,1);
5547 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5548 int *retPt=ret->getPointer();
5549 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5550 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5551 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5552 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5553 int *pt=newConn->getPointer();
5554 int *ptI=newConnI->getPointer();
5556 const int *oldc=_nodal_connec->getConstPointer();
5557 const int *ci=_nodal_connec_index->getConstPointer();
5558 for(int i=0;i<nbOfCells;i++,ci++)
5560 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5562 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5563 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5564 pt=std::copy(tmp,tmp+8,pt);
5573 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5574 ptI[1]=ptI[0]+ci[1]-ci[0];
5579 _nodal_connec->decrRef();
5580 _nodal_connec=newConn.retn();
5581 _nodal_connec_index->decrRef();
5582 _nodal_connec_index=newConnI.retn();
5589 * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5591 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5593 checkConnectivityFullyDefined();
5594 if(getMeshDimension()!=2)
5595 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5596 int nbOfCells=getNumberOfCells();
5597 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5598 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5599 ret->alloc(nbOfCells+nbOfCutCells,1);
5600 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5601 int *retPt=ret->getPointer();
5602 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5603 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5604 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5605 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5606 int *pt=newConn->getPointer();
5607 int *ptI=newConnI->getPointer();
5609 const int *oldc=_nodal_connec->getConstPointer();
5610 const int *ci=_nodal_connec_index->getConstPointer();
5611 for(int i=0;i<nbOfCells;i++,ci++)
5613 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5615 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5616 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5617 pt=std::copy(tmp,tmp+8,pt);
5626 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5627 ptI[1]=ptI[0]+ci[1]-ci[0];
5632 _nodal_connec->decrRef();
5633 _nodal_connec=newConn.retn();
5634 _nodal_connec_index->decrRef();
5635 _nodal_connec_index=newConnI.retn();
5642 * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5644 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5646 checkConnectivityFullyDefined();
5647 if(getMeshDimension()!=3)
5648 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5649 int nbOfCells=getNumberOfCells();
5650 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5651 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5652 ret->alloc(nbOfCells+4*nbOfCutCells,1);
5653 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5654 int *retPt=ret->getPointer();
5655 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5656 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5657 newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5658 newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5659 int *pt=newConn->getPointer();
5660 int *ptI=newConnI->getPointer();
5662 const int *oldc=_nodal_connec->getConstPointer();
5663 const int *ci=_nodal_connec_index->getConstPointer();
5664 for(int i=0;i<nbOfCells;i++,ci++)
5666 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5668 for(int j=0;j<5;j++,pt+=5,ptI++)
5670 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5671 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];
5678 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5679 ptI[1]=ptI[0]+ci[1]-ci[0];
5684 _nodal_connec->decrRef();
5685 _nodal_connec=newConn.retn();
5686 _nodal_connec_index->decrRef();
5687 _nodal_connec_index=newConnI.retn();
5694 * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5696 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5698 checkConnectivityFullyDefined();
5699 if(getMeshDimension()!=3)
5700 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5701 int nbOfCells=getNumberOfCells();
5702 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5703 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5704 ret->alloc(nbOfCells+5*nbOfCutCells,1);
5705 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5706 int *retPt=ret->getPointer();
5707 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5708 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5709 newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5710 newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5711 int *pt=newConn->getPointer();
5712 int *ptI=newConnI->getPointer();
5714 const int *oldc=_nodal_connec->getConstPointer();
5715 const int *ci=_nodal_connec_index->getConstPointer();
5716 for(int i=0;i<nbOfCells;i++,ci++)
5718 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5720 for(int j=0;j<6;j++,pt+=5,ptI++)
5722 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5723 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];
5730 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5731 ptI[1]=ptI[0]+ci[1]-ci[0];
5736 _nodal_connec->decrRef();
5737 _nodal_connec=newConn.retn();
5738 _nodal_connec_index->decrRef();
5739 _nodal_connec_index=newConnI.retn();
5746 * 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.
5747 * This method completly ignore coordinates.
5748 * \param nodeSubdived is the nodal connectivity of subdivision of edges
5749 * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5750 * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5751 * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5753 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5755 checkFullyDefined();
5756 if(getMeshDimension()!=2)
5757 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5758 int nbOfCells=getNumberOfCells();
5759 int *connI=_nodal_connec_index->getPointer();
5761 for(int i=0;i<nbOfCells;i++,connI++)
5763 int offset=descIndex[i];
5764 int nbOfEdges=descIndex[i+1]-offset;
5766 bool ddirect=desc[offset+nbOfEdges-1]>0;
5767 int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5768 int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5769 for(int j=0;j<nbOfEdges;j++)
5771 bool direct=desc[offset+j]>0;
5772 int edgeId=std::abs(desc[offset+j])-1;
5773 if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5775 int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5776 int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5777 int ref2=direct?id1:id2;
5780 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5781 newConnLgth+=nbOfSubNodes-1;
5786 std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5787 throw INTERP_KERNEL::Exception(oss.str().c_str());
5792 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5795 newConnLgth++;//+1 is for cell type
5796 connI[1]=newConnLgth;
5799 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5800 newConn->alloc(newConnLgth,1);
5801 int *work=newConn->getPointer();
5802 for(int i=0;i<nbOfCells;i++)
5804 *work++=INTERP_KERNEL::NORM_POLYGON;
5805 int offset=descIndex[i];
5806 int nbOfEdges=descIndex[i+1]-offset;
5807 for(int j=0;j<nbOfEdges;j++)
5809 bool direct=desc[offset+j]>0;
5810 int edgeId=std::abs(desc[offset+j])-1;
5812 work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5815 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5816 std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5817 work=std::copy(it,it+nbOfSubNodes-1,work);
5821 DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5824 _types.insert(INTERP_KERNEL::NORM_POLYGON);
5828 * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5829 * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5830 * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5831 * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5832 * so it can be useful to call mergeNodes() before calling this method.
5833 * \throw If \a this->getMeshDimension() <= 1.
5834 * \throw If the coordinates array is not set.
5835 * \throw If the nodal connectivity of cells is not defined.
5837 void MEDCouplingUMesh::convertDegeneratedCells()
5839 checkFullyDefined();
5840 if(getMeshDimension()<=1)
5841 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5842 int nbOfCells=getNumberOfCells();
5845 int initMeshLgth=getMeshLength();
5846 int *conn=_nodal_connec->getPointer();
5847 int *index=_nodal_connec_index->getPointer();
5851 for(int i=0;i<nbOfCells;i++)
5853 lgthOfCurCell=index[i+1]-posOfCurCell;
5854 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5856 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5857 conn+newPos+1,newLgth);
5858 conn[newPos]=newType;
5860 posOfCurCell=index[i+1];
5863 if(newPos!=initMeshLgth)
5864 _nodal_connec->reAlloc(newPos);
5869 * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5870 * A cell is considered to be oriented correctly if an angle between its
5871 * normal vector and a given vector is less than \c PI / \c 2.
5872 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5874 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5876 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5877 * is not cleared before filling in.
5878 * \throw If \a this->getMeshDimension() != 2.
5879 * \throw If \a this->getSpaceDimension() != 3.
5881 * \if ENABLE_EXAMPLES
5882 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5883 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5886 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
5888 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5889 throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5890 int nbOfCells=getNumberOfCells();
5891 const int *conn=_nodal_connec->getConstPointer();
5892 const int *connI=_nodal_connec_index->getConstPointer();
5893 const double *coordsPtr=_coords->getConstPointer();
5894 for(int i=0;i<nbOfCells;i++)
5896 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5897 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5899 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5900 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5907 * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5908 * considered to be oriented correctly if an angle between its normal vector and a
5909 * given vector is less than \c PI / \c 2.
5910 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5912 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5914 * \throw If \a this->getMeshDimension() != 2.
5915 * \throw If \a this->getSpaceDimension() != 3.
5917 * \if ENABLE_EXAMPLES
5918 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5919 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5922 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
5924 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5925 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5926 int nbOfCells=getNumberOfCells();
5927 int *conn=_nodal_connec->getPointer();
5928 const int *connI=_nodal_connec_index->getConstPointer();
5929 const double *coordsPtr=_coords->getConstPointer();
5930 bool isModified=false;
5931 for(int i=0;i<nbOfCells;i++)
5933 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5934 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5936 bool isQuadratic(INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic());
5937 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5942 std::vector<int> tmp(connI[i+1]-connI[i]-2);
5943 std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5944 std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5948 int sz(((int)(connI[i+1]-connI[i]-1))/2);
5949 std::vector<int> tmp0(sz-1),tmp1(sz);
5950 std::copy(conn+connI[i]+2,conn+connI[i]+1+sz,tmp0.rbegin());
5951 std::copy(conn+connI[i]+1+sz,conn+connI[i+1],tmp1.rbegin());
5952 std::copy(tmp0.begin(),tmp0.end(),conn+connI[i]+2);
5953 std::copy(tmp1.begin(),tmp1.end(),conn+connI[i]+1+sz);
5959 _nodal_connec->declareAsNew();
5964 * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5965 * oriented facets. The normal vector of the facet should point out of the cell.
5966 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5967 * is not cleared before filling in.
5968 * \throw If \a this->getMeshDimension() != 3.
5969 * \throw If \a this->getSpaceDimension() != 3.
5970 * \throw If the coordinates array is not set.
5971 * \throw If the nodal connectivity of cells is not defined.
5973 * \if ENABLE_EXAMPLES
5974 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5975 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5978 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
5980 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5981 throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5982 int nbOfCells=getNumberOfCells();
5983 const int *conn=_nodal_connec->getConstPointer();
5984 const int *connI=_nodal_connec_index->getConstPointer();
5985 const double *coordsPtr=_coords->getConstPointer();
5986 for(int i=0;i<nbOfCells;i++)
5988 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5989 if(type==INTERP_KERNEL::NORM_POLYHED)
5991 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5998 * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6000 * \throw If \a this->getMeshDimension() != 3.
6001 * \throw If \a this->getSpaceDimension() != 3.
6002 * \throw If the coordinates array is not set.
6003 * \throw If the nodal connectivity of cells is not defined.
6004 * \throw If the reparation fails.
6006 * \if ENABLE_EXAMPLES
6007 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6008 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6010 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6012 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
6014 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6015 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6016 int nbOfCells=getNumberOfCells();
6017 int *conn=_nodal_connec->getPointer();
6018 const int *connI=_nodal_connec_index->getConstPointer();
6019 const double *coordsPtr=_coords->getConstPointer();
6020 for(int i=0;i<nbOfCells;i++)
6022 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6023 if(type==INTERP_KERNEL::NORM_POLYHED)
6027 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6028 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6030 catch(INTERP_KERNEL::Exception& e)
6032 std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6033 throw INTERP_KERNEL::Exception(oss.str().c_str());
6041 * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6042 * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6043 * according to which the first facet of the cell should be oriented to have the normal vector
6044 * pointing out of cell.
6045 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6046 * cells. The caller is to delete this array using decrRef() as it is no more
6048 * \throw If \a this->getMeshDimension() != 3.
6049 * \throw If \a this->getSpaceDimension() != 3.
6050 * \throw If the coordinates array is not set.
6051 * \throw If the nodal connectivity of cells is not defined.
6053 * \if ENABLE_EXAMPLES
6054 * \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6055 * \ref py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6057 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6059 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6061 const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6062 if(getMeshDimension()!=3)
6063 throw INTERP_KERNEL::Exception(msg);
6064 int spaceDim=getSpaceDimension();
6066 throw INTERP_KERNEL::Exception(msg);
6068 int nbOfCells=getNumberOfCells();
6069 int *conn=_nodal_connec->getPointer();
6070 const int *connI=_nodal_connec_index->getConstPointer();
6071 const double *coo=getCoords()->getConstPointer();
6072 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6073 for(int i=0;i<nbOfCells;i++)
6075 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6076 if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6078 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6080 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6081 cells->pushBackSilent(i);
6085 return cells.retn();
6089 * This method is a faster method to correct orientation of all 3D cells in \a this.
6090 * 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.
6091 * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6093 * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6094 * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons,
6096 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6098 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6099 throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6100 int nbOfCells=getNumberOfCells();
6101 int *conn=_nodal_connec->getPointer();
6102 const int *connI=_nodal_connec_index->getConstPointer();
6103 const double *coordsPtr=_coords->getConstPointer();
6104 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6105 for(int i=0;i<nbOfCells;i++)
6107 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6110 case INTERP_KERNEL::NORM_TETRA4:
6112 if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6114 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6115 ret->pushBackSilent(i);
6119 case INTERP_KERNEL::NORM_PYRA5:
6121 if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6123 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6124 ret->pushBackSilent(i);
6128 case INTERP_KERNEL::NORM_PENTA6:
6129 case INTERP_KERNEL::NORM_HEXA8:
6130 case INTERP_KERNEL::NORM_HEXGP12:
6132 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6134 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6135 ret->pushBackSilent(i);
6139 case INTERP_KERNEL::NORM_POLYHED:
6141 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6143 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6144 ret->pushBackSilent(i);
6149 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 !");
6157 * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6158 * If it is not the case an exception will be thrown.
6159 * This method is fast because the first cell of \a this is used to compute the plane.
6160 * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6161 * \param pos output of size at least 3 used to store a point owned of searched plane.
6163 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6165 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6166 throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6167 const int *conn=_nodal_connec->getConstPointer();
6168 const int *connI=_nodal_connec_index->getConstPointer();
6169 const double *coordsPtr=_coords->getConstPointer();
6170 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6171 std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6175 * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6176 * cells. Currently cells of the following types are treated:
6177 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6178 * For a cell of other type an exception is thrown.
6179 * Space dimension of a 2D mesh can be either 2 or 3.
6180 * The Edge Ratio of a cell \f$t\f$ is:
6181 * \f$\frac{|t|_\infty}{|t|_0}\f$,
6182 * where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6183 * the smallest edge lengths of \f$t\f$.
6184 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6185 * cells and one time, lying on \a this mesh. The caller is to delete this
6186 * field using decrRef() as it is no more needed.
6187 * \throw If the coordinates array is not set.
6188 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6189 * \throw If the connectivity data array has more than one component.
6190 * \throw If the connectivity data array has a named component.
6191 * \throw If the connectivity index data array has more than one component.
6192 * \throw If the connectivity index data array has a named component.
6193 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6194 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6195 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6197 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6200 int spaceDim=getSpaceDimension();
6201 int meshDim=getMeshDimension();
6202 if(spaceDim!=2 && spaceDim!=3)
6203 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6204 if(meshDim!=2 && meshDim!=3)
6205 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6206 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6208 int nbOfCells=getNumberOfCells();
6209 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6210 arr->alloc(nbOfCells,1);
6211 double *pt=arr->getPointer();
6212 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6213 const int *conn=_nodal_connec->getConstPointer();
6214 const int *connI=_nodal_connec_index->getConstPointer();
6215 const double *coo=_coords->getConstPointer();
6217 for(int i=0;i<nbOfCells;i++,pt++)
6219 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6222 case INTERP_KERNEL::NORM_TRI3:
6224 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6225 *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6228 case INTERP_KERNEL::NORM_QUAD4:
6230 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6231 *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6234 case INTERP_KERNEL::NORM_TETRA4:
6236 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6237 *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6241 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6243 conn+=connI[i+1]-connI[i];
6245 ret->setName("EdgeRatio");
6246 ret->synchronizeTimeWithSupport();
6251 * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6252 * cells. Currently cells of the following types are treated:
6253 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6254 * For a cell of other type an exception is thrown.
6255 * Space dimension of a 2D mesh can be either 2 or 3.
6256 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6257 * cells and one time, lying on \a this mesh. The caller is to delete this
6258 * field using decrRef() as it is no more needed.
6259 * \throw If the coordinates array is not set.
6260 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6261 * \throw If the connectivity data array has more than one component.
6262 * \throw If the connectivity data array has a named component.
6263 * \throw If the connectivity index data array has more than one component.
6264 * \throw If the connectivity index data array has a named component.
6265 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6266 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6267 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6269 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6272 int spaceDim=getSpaceDimension();
6273 int meshDim=getMeshDimension();
6274 if(spaceDim!=2 && spaceDim!=3)
6275 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6276 if(meshDim!=2 && meshDim!=3)
6277 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6278 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6280 int nbOfCells=getNumberOfCells();
6281 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6282 arr->alloc(nbOfCells,1);
6283 double *pt=arr->getPointer();
6284 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6285 const int *conn=_nodal_connec->getConstPointer();
6286 const int *connI=_nodal_connec_index->getConstPointer();
6287 const double *coo=_coords->getConstPointer();
6289 for(int i=0;i<nbOfCells;i++,pt++)
6291 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6294 case INTERP_KERNEL::NORM_TRI3:
6296 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6297 *pt=INTERP_KERNEL::triAspectRatio(tmp);
6300 case INTERP_KERNEL::NORM_QUAD4:
6302 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6303 *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6306 case INTERP_KERNEL::NORM_TETRA4:
6308 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6309 *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6313 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6315 conn+=connI[i+1]-connI[i];
6317 ret->setName("AspectRatio");
6318 ret->synchronizeTimeWithSupport();
6323 * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6324 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6325 * treated: INTERP_KERNEL::NORM_QUAD4.
6326 * For a cell of other type an exception is thrown.
6327 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6328 * cells and one time, lying on \a this mesh. The caller is to delete this
6329 * field using decrRef() as it is no more needed.
6330 * \throw If the coordinates array is not set.
6331 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6332 * \throw If the connectivity data array has more than one component.
6333 * \throw If the connectivity data array has a named component.
6334 * \throw If the connectivity index data array has more than one component.
6335 * \throw If the connectivity index data array has a named component.
6336 * \throw If \a this->getMeshDimension() != 2.
6337 * \throw If \a this->getSpaceDimension() != 3.
6338 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6340 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6343 int spaceDim=getSpaceDimension();
6344 int meshDim=getMeshDimension();
6346 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6348 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6349 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6351 int nbOfCells=getNumberOfCells();
6352 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6353 arr->alloc(nbOfCells,1);
6354 double *pt=arr->getPointer();
6355 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6356 const int *conn=_nodal_connec->getConstPointer();
6357 const int *connI=_nodal_connec_index->getConstPointer();
6358 const double *coo=_coords->getConstPointer();
6360 for(int i=0;i<nbOfCells;i++,pt++)
6362 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6365 case INTERP_KERNEL::NORM_QUAD4:
6367 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6368 *pt=INTERP_KERNEL::quadWarp(tmp);
6372 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6374 conn+=connI[i+1]-connI[i];
6376 ret->setName("Warp");
6377 ret->synchronizeTimeWithSupport();
6383 * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6384 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6385 * treated: INTERP_KERNEL::NORM_QUAD4.
6386 * For a cell of other type an exception is thrown.
6387 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6388 * cells and one time, lying on \a this mesh. The caller is to delete this
6389 * field using decrRef() as it is no more needed.
6390 * \throw If the coordinates array is not set.
6391 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6392 * \throw If the connectivity data array has more than one component.
6393 * \throw If the connectivity data array has a named component.
6394 * \throw If the connectivity index data array has more than one component.
6395 * \throw If the connectivity index data array has a named component.
6396 * \throw If \a this->getMeshDimension() != 2.
6397 * \throw If \a this->getSpaceDimension() != 3.
6398 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6400 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6403 int spaceDim=getSpaceDimension();
6404 int meshDim=getMeshDimension();
6406 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6408 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6409 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6411 int nbOfCells=getNumberOfCells();
6412 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6413 arr->alloc(nbOfCells,1);
6414 double *pt=arr->getPointer();
6415 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6416 const int *conn=_nodal_connec->getConstPointer();
6417 const int *connI=_nodal_connec_index->getConstPointer();
6418 const double *coo=_coords->getConstPointer();
6420 for(int i=0;i<nbOfCells;i++,pt++)
6422 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6425 case INTERP_KERNEL::NORM_QUAD4:
6427 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6428 *pt=INTERP_KERNEL::quadSkew(tmp);
6432 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6434 conn+=connI[i+1]-connI[i];
6436 ret->setName("Skew");
6437 ret->synchronizeTimeWithSupport();
6442 * This method aggregate the bbox of each cell and put it into bbox parameter.
6444 * \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)
6445 * For all other cases this input parameter is ignored.
6446 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6448 * \throw If \a this is not fully set (coordinates and connectivity).
6449 * \throw If a cell in \a this has no valid nodeId.
6450 * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6452 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6454 int mDim(getMeshDimension()),sDim(getSpaceDimension());
6455 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.
6456 return getBoundingBoxForBBTreeFast();
6457 if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6459 bool presenceOfQuadratic(false);
6460 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6462 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6463 if(cm.isQuadratic())
6464 presenceOfQuadratic=true;
6466 if(!presenceOfQuadratic)
6467 return getBoundingBoxForBBTreeFast();
6468 if(mDim==2 && sDim==2)
6469 return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6471 return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6473 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) !");
6477 * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6478 * So meshes having quadratic cells the computed bounding boxes can be invalid !
6480 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6482 * \throw If \a this is not fully set (coordinates and connectivity).
6483 * \throw If a cell in \a this has no valid nodeId.
6485 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6487 checkFullyDefined();
6488 int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6489 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6490 double *bbox(ret->getPointer());
6491 for(int i=0;i<nbOfCells*spaceDim;i++)
6493 bbox[2*i]=std::numeric_limits<double>::max();
6494 bbox[2*i+1]=-std::numeric_limits<double>::max();
6496 const double *coordsPtr(_coords->getConstPointer());
6497 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6498 for(int i=0;i<nbOfCells;i++)
6500 int offset=connI[i]+1;
6501 int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6502 for(int j=0;j<nbOfNodesForCell;j++)
6504 int nodeId=conn[offset+j];
6505 if(nodeId>=0 && nodeId<nbOfNodes)
6507 for(int k=0;k<spaceDim;k++)
6509 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6510 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6517 std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6518 throw INTERP_KERNEL::Exception(oss.str().c_str());
6525 * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6526 * useful for 2D meshes having quadratic cells
6527 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6528 * the two extremities of the arc of circle).
6530 * \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)
6531 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6532 * \throw If \a this is not fully defined.
6533 * \throw If \a this is not a mesh with meshDimension equal to 2.
6534 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6535 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6537 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6539 checkFullyDefined();
6540 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6541 if(spaceDim!=2 || mDim!=2)
6542 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!");
6543 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6544 double *bbox(ret->getPointer());
6545 const double *coords(_coords->getConstPointer());
6546 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6547 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6549 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6550 int sz(connI[1]-connI[0]-1);
6551 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6552 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6553 INTERP_KERNEL::QuadraticPolygon *pol(0);
6554 for(int j=0;j<sz;j++)
6556 int nodeId(conn[*connI+1+j]);
6557 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6559 if(!cm.isQuadratic())
6560 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6562 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6563 INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6564 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax();
6570 * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6571 * useful for 2D meshes having quadratic cells
6572 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6573 * the two extremities of the arc of circle).
6575 * \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)
6576 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6577 * \throw If \a this is not fully defined.
6578 * \throw If \a this is not a mesh with meshDimension equal to 1.
6579 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6580 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6582 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6584 checkFullyDefined();
6585 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6586 if(spaceDim!=2 || mDim!=1)
6587 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!");
6588 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6589 double *bbox(ret->getPointer());
6590 const double *coords(_coords->getConstPointer());
6591 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6592 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6594 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6595 int sz(connI[1]-connI[0]-1);
6596 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6597 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6598 INTERP_KERNEL::Edge *edge(0);
6599 for(int j=0;j<sz;j++)
6601 int nodeId(conn[*connI+1+j]);
6602 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6604 if(!cm.isQuadratic())
6605 edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6607 edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6608 const INTERP_KERNEL::Bounds& b(edge->getBounds());
6609 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6616 namespace ParaMEDMEMImpl
6621 ConnReader(const int *c, int val):_conn(c),_val(val) { }
6622 bool operator() (const int& pos) { return _conn[pos]!=_val; }
6631 ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6632 bool operator() (const int& pos) { return _conn[pos]==_val; }
6642 * This method expects that \a this is sorted by types. If not an exception will be thrown.
6643 * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6644 * \a this is composed in cell types.
6645 * The returned array is of size 3*n where n is the number of different types present in \a this.
6646 * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here.
6647 * This parameter is kept only for compatibility with other methode listed above.
6649 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6651 checkConnectivityFullyDefined();
6652 const int *conn=_nodal_connec->getConstPointer();
6653 const int *connI=_nodal_connec_index->getConstPointer();
6654 const int *work=connI;
6655 int nbOfCells=getNumberOfCells();
6656 std::size_t n=getAllGeoTypes().size();
6657 std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6658 std::set<INTERP_KERNEL::NormalizedCellType> types;
6659 for(std::size_t i=0;work!=connI+nbOfCells;i++)
6661 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6662 if(types.find(typ)!=types.end())
6664 std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6665 oss << " is not contiguous !";
6666 throw INTERP_KERNEL::Exception(oss.str().c_str());
6670 const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6671 ret[3*i+1]=(int)std::distance(work,work2);
6678 * This method is used to check that this has contiguous cell type in same order than described in \a code.
6679 * only for types cell, type node is not managed.
6680 * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6681 * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6682 * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6683 * If 2 or more same geometric type is in \a code and exception is thrown too.
6685 * This method firstly checks
6686 * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6687 * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6688 * an exception is thrown too.
6690 * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6691 * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown
6692 * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6694 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6697 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6698 std::size_t sz=code.size();
6701 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6702 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6704 bool isNoPflUsed=true;
6705 for(std::size_t i=0;i<n;i++)
6706 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6708 types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6710 if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6711 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6712 isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6715 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6718 if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6719 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6720 if(types.size()==_types.size())
6723 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6725 int *retPtr=ret->getPointer();
6726 const int *connI=_nodal_connec_index->getConstPointer();
6727 const int *conn=_nodal_connec->getConstPointer();
6728 int nbOfCells=getNumberOfCells();
6731 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6733 i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6734 int offset=(int)std::distance(connI,i);
6735 const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6736 int nbOfCellsOfCurType=(int)std::distance(i,j);
6737 if(code[3*kk+2]==-1)
6738 for(int k=0;k<nbOfCellsOfCurType;k++)
6742 int idInIdsPerType=code[3*kk+2];
6743 if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6745 const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6748 zePfl->checkAllocated();
6749 if(zePfl->getNumberOfComponents()==1)
6751 for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6753 if(*k>=0 && *k<nbOfCellsOfCurType)
6754 *retPtr=(*k)+offset;
6757 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6758 oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6759 throw INTERP_KERNEL::Exception(oss.str().c_str());
6764 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6767 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6771 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6772 oss << " should be in [0," << idsPerType.size() << ") !";
6773 throw INTERP_KERNEL::Exception(oss.str().c_str());
6782 * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6783 * 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.
6784 * 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.
6785 * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6787 * \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.
6788 * \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,
6789 * \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6790 * \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.
6791 * This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6792 * \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
6794 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6797 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6798 if(profile->getNumberOfComponents()!=1)
6799 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6800 checkConnectivityFullyDefined();
6801 const int *conn=_nodal_connec->getConstPointer();
6802 const int *connI=_nodal_connec_index->getConstPointer();
6803 int nbOfCells=getNumberOfCells();
6804 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6805 std::vector<int> typeRangeVals(1);
6806 for(const int *i=connI;i!=connI+nbOfCells;)
6808 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6809 if(std::find(types.begin(),types.end(),curType)!=types.end())
6811 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6813 types.push_back(curType);
6814 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6815 typeRangeVals.push_back((int)std::distance(connI,i));
6818 DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6819 profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6820 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6821 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6822 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6824 int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6825 code.resize(3*nbOfCastsFinal);
6826 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6827 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6828 for(int i=0;i<nbOfCastsFinal;i++)
6830 int castId=castsPresent->getIJ(i,0);
6831 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6832 idsInPflPerType2.push_back(tmp3);
6833 code[3*i]=(int)types[castId];
6834 code[3*i+1]=tmp3->getNumberOfTuples();
6835 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6836 if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6838 tmp4->copyStringInfoFrom(*profile);
6839 idsPerType2.push_back(tmp4);
6840 code[3*i+2]=(int)idsPerType2.size()-1;
6847 std::size_t sz2=idsInPflPerType2.size();
6848 idsInPflPerType.resize(sz2);
6849 for(std::size_t i=0;i<sz2;i++)
6851 DataArrayInt *locDa=idsInPflPerType2[i];
6853 idsInPflPerType[i]=locDa;
6855 std::size_t sz=idsPerType2.size();
6856 idsPerType.resize(sz);
6857 for(std::size_t i=0;i<sz;i++)
6859 DataArrayInt *locDa=idsPerType2[i];
6861 idsPerType[i]=locDa;
6866 * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6867 * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6868 * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6869 * 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.
6871 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
6873 checkFullyDefined();
6874 nM1LevMesh->checkFullyDefined();
6875 if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6876 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6877 if(_coords!=nM1LevMesh->getCoords())
6878 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6879 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6880 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6881 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6882 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6883 desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6884 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6885 tmp->setConnectivity(tmp0,tmp1);
6886 tmp->renumberCells(ret0->getConstPointer(),false);
6887 revDesc=tmp->getNodalConnectivity();
6888 revDescIndx=tmp->getNodalConnectivityIndex();
6889 DataArrayInt *ret=0;
6890 if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6893 ret->getMaxValue(tmp2);
6895 std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6896 throw INTERP_KERNEL::Exception(oss.str().c_str());
6901 revDescIndx->incrRef();
6904 meshnM1Old2New=ret0;
6909 * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6910 * necessary for writing the mesh to MED file. Additionally returns a permutation array
6911 * in "Old to New" mode.
6912 * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6913 * this array using decrRef() as it is no more needed.
6914 * \throw If the nodal connectivity of cells is not defined.
6916 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
6918 checkConnectivityFullyDefined();
6919 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6920 renumberCells(ret->getConstPointer(),false);
6925 * This methods checks that cells are sorted by their types.
6926 * This method makes asumption (no check) that connectivity is correctly set before calling.
6928 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6930 checkFullyDefined();
6931 const int *conn=_nodal_connec->getConstPointer();
6932 const int *connI=_nodal_connec_index->getConstPointer();
6933 int nbOfCells=getNumberOfCells();
6934 std::set<INTERP_KERNEL::NormalizedCellType> types;
6935 for(const int *i=connI;i!=connI+nbOfCells;)
6937 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6938 if(types.find(curType)!=types.end())
6940 types.insert(curType);
6941 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6947 * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6948 * The geometric type order is specified by MED file.
6950 * \sa MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6952 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
6954 return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6958 * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6959 * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
6960 * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6961 * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6963 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6965 checkFullyDefined();
6966 const int *conn=_nodal_connec->getConstPointer();
6967 const int *connI=_nodal_connec_index->getConstPointer();
6968 int nbOfCells=getNumberOfCells();
6972 std::set<INTERP_KERNEL::NormalizedCellType> sg;
6973 for(const int *i=connI;i!=connI+nbOfCells;)
6975 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6976 const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6977 if(isTypeExists!=orderEnd)
6979 int pos=(int)std::distance(orderBg,isTypeExists);
6983 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6987 if(sg.find(curType)==sg.end())
6989 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7000 * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
7001 * 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
7002 * 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'.
7004 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
7006 checkConnectivityFullyDefined();
7007 int nbOfCells=getNumberOfCells();
7008 const int *conn=_nodal_connec->getConstPointer();
7009 const int *connI=_nodal_connec_index->getConstPointer();
7010 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
7011 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
7012 tmpa->alloc(nbOfCells,1);
7013 tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
7014 tmpb->fillWithZero();
7015 int *tmp=tmpa->getPointer();
7016 int *tmp2=tmpb->getPointer();
7017 for(const int *i=connI;i!=connI+nbOfCells;i++)
7019 const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
7022 int pos=(int)std::distance(orderBg,where);
7024 tmp[std::distance(connI,i)]=pos;
7028 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
7029 std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
7030 oss << " has a type " << cm.getRepr() << " not in input array of type !";
7031 throw INTERP_KERNEL::Exception(oss.str().c_str());
7034 nbPerType=tmpb.retn();
7039 * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7041 * \return a new object containing the old to new correspondance.
7043 * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7045 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7047 return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7051 * 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.
7052 * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7053 * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7054 * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7056 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7058 DataArrayInt *nbPerType=0;
7059 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7060 nbPerType->decrRef();
7061 return tmpa->buildPermArrPerLevel();
7065 * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7066 * The number of cells remains unchanged after the call of this method.
7067 * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7068 * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7070 * \return the array giving the correspondance old to new.
7072 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7074 checkFullyDefined();
7076 const int *conn=_nodal_connec->getConstPointer();
7077 const int *connI=_nodal_connec_index->getConstPointer();
7078 int nbOfCells=getNumberOfCells();
7079 std::vector<INTERP_KERNEL::NormalizedCellType> types;
7080 for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7081 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7083 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7084 types.push_back(curType);
7085 for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7087 DataArrayInt *ret=DataArrayInt::New();
7088 ret->alloc(nbOfCells,1);
7089 int *retPtr=ret->getPointer();
7090 std::fill(retPtr,retPtr+nbOfCells,-1);
7092 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7094 for(const int *i=connI;i!=connI+nbOfCells;i++)
7095 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7096 retPtr[std::distance(connI,i)]=newCellId++;
7098 renumberCells(retPtr,false);
7103 * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7104 * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7105 * This method makes asumption that connectivity is correctly set before calling.
7107 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7109 checkConnectivityFullyDefined();
7110 const int *conn=_nodal_connec->getConstPointer();
7111 const int *connI=_nodal_connec_index->getConstPointer();
7112 int nbOfCells=getNumberOfCells();
7113 std::vector<MEDCouplingUMesh *> ret;
7114 for(const int *i=connI;i!=connI+nbOfCells;)
7116 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7117 int beginCellId=(int)std::distance(connI,i);
7118 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7119 int endCellId=(int)std::distance(connI,i);
7120 int sz=endCellId-beginCellId;
7121 int *cells=new int[sz];
7122 for(int j=0;j<sz;j++)
7123 cells[j]=beginCellId+j;
7124 MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7132 * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7133 * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7134 * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7136 * \return a newly allocated instance, that the caller must manage.
7137 * \throw If \a this contains more than one geometric type.
7138 * \throw If the nodal connectivity of \a this is not fully defined.
7139 * \throw If the internal data is not coherent.
7141 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7143 checkConnectivityFullyDefined();
7144 if(_types.size()!=1)
7145 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7146 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7147 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7148 ret->setCoords(getCoords());
7149 MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7152 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7153 retC->setNodalConnectivity(c);
7157 MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7159 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7160 DataArrayInt *c=0,*ci=0;
7161 convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7162 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7163 retD->setNodalConnectivity(cs,cis);
7168 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7170 checkConnectivityFullyDefined();
7171 if(_types.size()!=1)
7172 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7173 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7174 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7177 std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7178 oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7179 throw INTERP_KERNEL::Exception(oss.str().c_str());
7181 int nbCells=getNumberOfCells();
7183 int nbNodesPerCell=(int)cm.getNumberOfNodes();
7184 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7185 int *outPtr=connOut->getPointer();
7186 const int *conn=_nodal_connec->begin();
7187 const int *connI=_nodal_connec_index->begin();
7189 for(int i=0;i<nbCells;i++,connI++)
7191 if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7192 outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7195 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 << ") !";
7196 throw INTERP_KERNEL::Exception(oss.str().c_str());
7199 return connOut.retn();
7202 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7204 static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7205 checkConnectivityFullyDefined();
7206 if(_types.size()!=1)
7207 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7208 int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7210 throw INTERP_KERNEL::Exception(msg0);
7211 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7212 c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7213 int *cp(c->getPointer()),*cip(ci->getPointer());
7214 const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7216 for(int i=0;i<nbCells;i++,cip++,incip++)
7218 int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7219 int delta(stop-strt);
7222 if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7223 cp=std::copy(incp+strt,incp+stop,cp);
7225 throw INTERP_KERNEL::Exception(msg0);
7228 throw INTERP_KERNEL::Exception(msg0);
7229 cip[1]=cip[0]+delta;
7231 nodalConn=c.retn(); nodalConnIndex=ci.retn();
7235 * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7236 * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7237 * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7238 * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7239 * are not used here to avoid the build of big permutation array.
7241 * \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
7242 * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7243 * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7244 * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7245 * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7246 * output array gives for each chunck of same type the corresponding mesh id in \b ms.
7247 * \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
7248 * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7250 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7251 DataArrayInt *&szOfCellGrpOfSameType,
7252 DataArrayInt *&idInMsOfCellGrpOfSameType)
7254 std::vector<const MEDCouplingUMesh *> ms2;
7255 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7258 (*it)->checkConnectivityFullyDefined();
7262 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7263 const DataArrayDouble *refCoo=ms2[0]->getCoords();
7264 int meshDim=ms2[0]->getMeshDimension();
7265 std::vector<const MEDCouplingUMesh *> m1ssm;
7266 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7268 std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7269 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7271 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7272 ret1->alloc(0,1); ret2->alloc(0,1);
7273 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7275 if(meshDim!=(*it)->getMeshDimension())
7276 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7277 if(refCoo!=(*it)->getCoords())
7278 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7279 std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7280 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7281 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7282 for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7284 MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7285 m1ssmSingleAuto.push_back(singleCell);
7286 m1ssmSingle.push_back(singleCell);
7287 ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7290 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7291 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7292 std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7293 for(std::size_t i=0;i<m1ssm.size();i++)
7294 m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7295 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7296 szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7297 idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7302 * This method returns a newly created DataArrayInt instance.
7303 * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7305 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7307 checkFullyDefined();
7308 const int *conn=_nodal_connec->getConstPointer();
7309 const int *connIndex=_nodal_connec_index->getConstPointer();
7310 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7311 for(const int *w=begin;w!=end;w++)
7312 if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7313 ret->pushBackSilent(*w);
7318 * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7319 * are in [0:getNumberOfCells())
7321 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7323 checkFullyDefined();
7324 const int *conn=_nodal_connec->getConstPointer();
7325 const int *connI=_nodal_connec_index->getConstPointer();
7326 int nbOfCells=getNumberOfCells();
7327 std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7328 int *tmp=new int[nbOfCells];
7329 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7332 for(const int *i=connI;i!=connI+nbOfCells;i++)
7333 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7334 tmp[std::distance(connI,i)]=j++;
7336 DataArrayInt *ret=DataArrayInt::New();
7337 ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7338 ret->copyStringInfoFrom(*da);
7339 int *retPtr=ret->getPointer();
7340 const int *daPtr=da->getConstPointer();
7341 int nbOfElems=da->getNbOfElems();
7342 for(int k=0;k<nbOfElems;k++)
7343 retPtr[k]=tmp[daPtr[k]];
7349 * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7350 * This method \b works \b for mesh sorted by type.
7351 * cells whose ids is in 'idsPerGeoType' array.
7352 * This method conserves coords and name of mesh.
7354 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7356 std::vector<int> code=getDistributionOfTypes();
7357 std::size_t nOfTypesInThis=code.size()/3;
7358 int sz=0,szOfType=0;
7359 for(std::size_t i=0;i<nOfTypesInThis;i++)
7364 szOfType=code[3*i+1];
7366 for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7367 if(*work<0 || *work>=szOfType)
7369 std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7370 oss << ". It should be in [0," << szOfType << ") !";
7371 throw INTERP_KERNEL::Exception(oss.str().c_str());
7373 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7374 int *idsPtr=idsTokeep->getPointer();
7376 for(std::size_t i=0;i<nOfTypesInThis;i++)
7379 for(int j=0;j<code[3*i+1];j++)
7382 idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7383 offset+=code[3*i+1];
7385 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7386 ret->copyTinyInfoFrom(this);
7391 * This method returns a vector of size 'this->getNumberOfCells()'.
7392 * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7394 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7396 int ncell=getNumberOfCells();
7397 std::vector<bool> ret(ncell);
7398 const int *cI=getNodalConnectivityIndex()->getConstPointer();
7399 const int *c=getNodalConnectivity()->getConstPointer();
7400 for(int i=0;i<ncell;i++)
7402 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7403 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7404 ret[i]=cm.isQuadratic();
7410 * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7412 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7414 if(other->getType()!=UNSTRUCTURED)
7415 throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7416 const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7417 return MergeUMeshes(this,otherC);
7421 * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7422 * computed by averaging coordinates of cell nodes, so this method is not a right
7423 * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7424 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7425 * this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7426 * components. The caller is to delete this array using decrRef() as it is
7428 * \throw If the coordinates array is not set.
7429 * \throw If the nodal connectivity of cells is not defined.
7430 * \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7432 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7434 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7435 int spaceDim=getSpaceDimension();
7436 int nbOfCells=getNumberOfCells();
7437 ret->alloc(nbOfCells,spaceDim);
7438 ret->copyStringInfoFrom(*getCoords());
7439 double *ptToFill=ret->getPointer();
7440 const int *nodal=_nodal_connec->getConstPointer();
7441 const int *nodalI=_nodal_connec_index->getConstPointer();
7442 const double *coor=_coords->getConstPointer();
7443 for(int i=0;i<nbOfCells;i++)
7445 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7446 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7453 * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7454 * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the
7456 * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned
7457 * DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7459 * \sa MEDCouplingUMesh::getBarycenterAndOwner
7460 * \throw If \a this is not fully defined (coordinates and connectivity)
7461 * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7463 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7465 checkFullyDefined();
7466 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7467 int spaceDim=getSpaceDimension();
7468 int nbOfCells=getNumberOfCells();
7469 int nbOfNodes=getNumberOfNodes();
7470 ret->alloc(nbOfCells,spaceDim);
7471 double *ptToFill=ret->getPointer();
7472 const int *nodal=_nodal_connec->getConstPointer();
7473 const int *nodalI=_nodal_connec_index->getConstPointer();
7474 const double *coor=_coords->getConstPointer();
7475 for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7477 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7478 std::fill(ptToFill,ptToFill+spaceDim,0.);
7479 if(type!=INTERP_KERNEL::NORM_POLYHED)
7481 for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7483 if(*conn>=0 && *conn<nbOfNodes)
7484 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7487 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," << nbOfNodes << ") !";
7488 throw INTERP_KERNEL::Exception(oss.str().c_str());
7491 int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7492 if(nbOfNodesInCell>0)
7493 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7496 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7497 throw INTERP_KERNEL::Exception(oss.str().c_str());
7502 std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7504 for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7506 if(*it>=0 && *it<nbOfNodes)
7507 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7510 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," << nbOfNodes << ") !";
7511 throw INTERP_KERNEL::Exception(oss.str().c_str());
7515 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7518 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7519 throw INTERP_KERNEL::Exception(oss.str().c_str());
7527 * Returns a new DataArrayDouble holding barycenters of specified cells. The
7528 * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7529 * are specified via an array of cell ids.
7530 * \warning Validity of the specified cell ids is not checked!
7531 * Valid range is [ 0, \a this->getNumberOfCells() ).
7532 * \param [in] begin - an array of cell ids of interest.
7533 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7534 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7535 * end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7536 * caller is to delete this array using decrRef() as it is no more needed.
7537 * \throw If the coordinates array is not set.
7538 * \throw If the nodal connectivity of cells is not defined.
7540 * \if ENABLE_EXAMPLES
7541 * \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7542 * \ref py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7545 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7547 DataArrayDouble *ret=DataArrayDouble::New();
7548 int spaceDim=getSpaceDimension();
7549 int nbOfTuple=(int)std::distance(begin,end);
7550 ret->alloc(nbOfTuple,spaceDim);
7551 double *ptToFill=ret->getPointer();
7552 double *tmp=new double[spaceDim];
7553 const int *nodal=_nodal_connec->getConstPointer();
7554 const int *nodalI=_nodal_connec_index->getConstPointer();
7555 const double *coor=_coords->getConstPointer();
7556 for(const int *w=begin;w!=end;w++)
7558 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7559 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7567 * 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".
7568 * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7569 * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7570 * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7571 * This method is useful to detect 2D cells in 3D space that are not coplanar.
7573 * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7574 * \throw If spaceDim!=3 or meshDim!=2.
7575 * \throw If connectivity of \a this is invalid.
7576 * \throw If connectivity of a cell in \a this points to an invalid node.
7578 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7580 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7581 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7582 if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7583 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7584 ret->alloc(nbOfCells,4);
7585 double *retPtr(ret->getPointer());
7586 const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7587 const double *coor(_coords->begin());
7588 for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7590 double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7591 if(nodalI[1]-nodalI[0]>=3)
7593 for(int j=0;j<3;j++)
7595 int nodeId(nodal[nodalI[0]+1+j]);
7596 if(nodeId>=0 && nodeId<nbOfNodes)
7597 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7600 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7601 throw INTERP_KERNEL::Exception(oss.str().c_str());
7607 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7608 throw INTERP_KERNEL::Exception(oss.str().c_str());
7610 INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7611 retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7617 * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7620 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7623 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7624 da->checkAllocated();
7625 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7627 int nbOfTuples=da->getNumberOfTuples();
7628 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7629 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7630 c->alloc(2*nbOfTuples,1);
7631 cI->alloc(nbOfTuples+1,1);
7632 int *cp=c->getPointer();
7633 int *cip=cI->getPointer();
7635 for(int i=0;i<nbOfTuples;i++)
7637 *cp++=INTERP_KERNEL::NORM_POINT1;
7641 ret->setConnectivity(c,cI,true);
7645 * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7646 * Cells and nodes of
7647 * the first mesh precede cells and nodes of the second mesh within the result mesh.
7648 * \param [in] mesh1 - the first mesh.
7649 * \param [in] mesh2 - the second mesh.
7650 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7651 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7652 * is no more needed.
7653 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7654 * \throw If the coordinates array is not set in none of the meshes.
7655 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7656 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7658 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7660 std::vector<const MEDCouplingUMesh *> tmp(2);
7661 tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7662 return MergeUMeshes(tmp);
7666 * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7667 * Cells and nodes of
7668 * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7669 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7670 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7671 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7672 * is no more needed.
7673 * \throw If \a a.size() == 0.
7674 * \throw If \a a[ *i* ] == NULL.
7675 * \throw If the coordinates array is not set in none of the meshes.
7676 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7677 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7679 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7681 std::size_t sz=a.size();
7683 return MergeUMeshesLL(a);
7684 for(std::size_t ii=0;ii<sz;ii++)
7687 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7688 throw INTERP_KERNEL::Exception(oss.str().c_str());
7690 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7691 std::vector< const MEDCouplingUMesh * > aa(sz);
7693 for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7695 const MEDCouplingUMesh *cur=a[i];
7696 const DataArrayDouble *coo=cur->getCoords();
7698 spaceDim=coo->getNumberOfComponents();
7701 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7702 for(std::size_t i=0;i<sz;i++)
7704 bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7707 return MergeUMeshesLL(aa);
7712 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7715 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7716 std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7717 int meshDim=(*it)->getMeshDimension();
7718 int nbOfCells=(*it)->getNumberOfCells();
7719 int meshLgth=(*it++)->getMeshLength();
7720 for(;it!=a.end();it++)
7722 if(meshDim!=(*it)->getMeshDimension())
7723 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7724 nbOfCells+=(*it)->getNumberOfCells();
7725 meshLgth+=(*it)->getMeshLength();
7727 std::vector<const MEDCouplingPointSet *> aps(a.size());
7728 std::copy(a.begin(),a.end(),aps.begin());
7729 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7730 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7731 ret->setCoords(pts);
7732 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7733 c->alloc(meshLgth,1);
7734 int *cPtr=c->getPointer();
7735 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7736 cI->alloc(nbOfCells+1,1);
7737 int *cIPtr=cI->getPointer();
7741 for(it=a.begin();it!=a.end();it++)
7743 int curNbOfCell=(*it)->getNumberOfCells();
7744 const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7745 const int *curC=(*it)->_nodal_connec->getConstPointer();
7746 cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7747 for(int j=0;j<curNbOfCell;j++)
7749 const int *src=curC+curCI[j];
7751 for(;src!=curC+curCI[j+1];src++,cPtr++)
7759 offset+=curCI[curNbOfCell];
7760 offset2+=(*it)->getNumberOfNodes();
7763 ret->setConnectivity(c,cI,true);
7770 * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7771 * dimension and sharing the node coordinates array.
7772 * All cells of the first mesh precede all cells of the second mesh
7773 * within the result mesh.
7774 * \param [in] mesh1 - the first mesh.
7775 * \param [in] mesh2 - the second mesh.
7776 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7777 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7778 * is no more needed.
7779 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7780 * \throw If the meshes do not share the node coordinates array.
7781 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7782 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7784 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7786 std::vector<const MEDCouplingUMesh *> tmp(2);
7787 tmp[0]=mesh1; tmp[1]=mesh2;
7788 return MergeUMeshesOnSameCoords(tmp);
7792 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7793 * dimension and sharing the node coordinates array.
7794 * All cells of the *i*-th mesh precede all cells of the
7795 * (*i*+1)-th mesh within the result mesh.
7796 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7797 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7798 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7799 * is no more needed.
7800 * \throw If \a a.size() == 0.
7801 * \throw If \a a[ *i* ] == NULL.
7802 * \throw If the meshes do not share the node coordinates array.
7803 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7804 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7806 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7809 throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7810 for(std::size_t ii=0;ii<meshes.size();ii++)
7813 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7814 throw INTERP_KERNEL::Exception(oss.str().c_str());
7816 const DataArrayDouble *coords=meshes.front()->getCoords();
7817 int meshDim=meshes.front()->getMeshDimension();
7818 std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7820 int meshIndexLgth=0;
7821 for(;iter!=meshes.end();iter++)
7823 if(coords!=(*iter)->getCoords())
7824 throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7825 if(meshDim!=(*iter)->getMeshDimension())
7826 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7827 meshLgth+=(*iter)->getMeshLength();
7828 meshIndexLgth+=(*iter)->getNumberOfCells();
7830 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7831 nodal->alloc(meshLgth,1);
7832 int *nodalPtr=nodal->getPointer();
7833 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7834 nodalIndex->alloc(meshIndexLgth+1,1);
7835 int *nodalIndexPtr=nodalIndex->getPointer();
7837 for(iter=meshes.begin();iter!=meshes.end();iter++)
7839 const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7840 const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7841 int nbOfCells=(*iter)->getNumberOfCells();
7842 int meshLgth2=(*iter)->getMeshLength();
7843 nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7844 if(iter!=meshes.begin())
7845 nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7847 nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7850 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7851 ret->setName("merge");
7852 ret->setMeshDimension(meshDim);
7853 ret->setConnectivity(nodal,nodalIndex,true);
7854 ret->setCoords(coords);
7859 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7860 * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7861 * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7862 * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7863 * New" mode are returned for each input mesh.
7864 * \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7865 * \param [in] compType - specifies a cell comparison technique. For meaning of its
7866 * valid values [0,1,2], see zipConnectivityTraducer().
7867 * \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7868 * meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7869 * mesh. The caller is to delete each of the arrays using decrRef() as it is
7871 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7872 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7873 * is no more needed.
7874 * \throw If \a meshes.size() == 0.
7875 * \throw If \a meshes[ *i* ] == NULL.
7876 * \throw If the meshes do not share the node coordinates array.
7877 * \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7878 * \throw If the \a meshes are of different dimension (getMeshDimension()).
7879 * \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7880 * \throw If the nodal connectivity any of \a meshes includes an invalid id.
7882 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7884 //All checks are delegated to MergeUMeshesOnSameCoords
7885 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7886 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7887 corr.resize(meshes.size());
7888 std::size_t nbOfMeshes=meshes.size();
7890 const int *o2nPtr=o2n->getConstPointer();
7891 for(std::size_t i=0;i<nbOfMeshes;i++)
7893 DataArrayInt *tmp=DataArrayInt::New();
7894 int curNbOfCells=meshes[i]->getNumberOfCells();
7895 tmp->alloc(curNbOfCells,1);
7896 std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7897 offset+=curNbOfCells;
7898 tmp->setName(meshes[i]->getName());
7905 * Makes all given meshes share the nodal connectivity array. The common connectivity
7906 * array is created by concatenating the connectivity arrays of all given meshes. All
7907 * the given meshes must be of the same space dimension but dimension of cells **can
7908 * differ**. This method is particulary useful in MEDLoader context to build a \ref
7909 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7910 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7911 * \param [in,out] meshes - a vector of meshes to update.
7912 * \throw If any of \a meshes is NULL.
7913 * \throw If the coordinates array is not set in any of \a meshes.
7914 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7915 * \throw If \a meshes are of different space dimension.
7917 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
7919 std::size_t sz=meshes.size();
7922 std::vector< const DataArrayDouble * > coords(meshes.size());
7923 std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7924 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7928 (*it)->checkConnectivityFullyDefined();
7929 const DataArrayDouble *coo=(*it)->getCoords();
7934 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7935 oss << " has no coordinate array defined !";
7936 throw INTERP_KERNEL::Exception(oss.str().c_str());
7941 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7942 oss << " is null !";
7943 throw INTERP_KERNEL::Exception(oss.str().c_str());
7946 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7947 std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7948 int offset=(*it)->getNumberOfNodes();
7949 (*it++)->setCoords(res);
7950 for(;it!=meshes.end();it++)
7952 int oldNumberOfNodes=(*it)->getNumberOfNodes();
7953 (*it)->setCoords(res);
7954 (*it)->shiftNodeNumbersInConn(offset);
7955 offset+=oldNumberOfNodes;
7960 * Merges nodes coincident with a given precision within all given meshes that share
7961 * the nodal connectivity array. The given meshes **can be of different** mesh
7962 * dimension. This method is particulary useful in MEDLoader context to build a \ref
7963 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7964 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7965 * \param [in,out] meshes - a vector of meshes to update.
7966 * \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7967 * \throw If any of \a meshes is NULL.
7968 * \throw If the \a meshes do not share the same node coordinates array.
7969 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7971 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
7975 std::set<const DataArrayDouble *> s;
7976 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7979 s.insert((*it)->getCoords());
7982 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 !";
7983 throw INTERP_KERNEL::Exception(oss.str().c_str());
7988 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 !";
7989 throw INTERP_KERNEL::Exception(oss.str().c_str());
7991 const DataArrayDouble *coo=*(s.begin());
7995 DataArrayInt *comm,*commI;
7996 coo->findCommonTuples(eps,-1,comm,commI);
7997 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7998 int oldNbOfNodes=coo->getNumberOfTuples();
8000 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
8001 if(oldNbOfNodes==newNbOfNodes)
8003 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
8004 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8006 (*it)->renumberNodesInConn(o2n->getConstPointer());
8007 (*it)->setCoords(newCoords);
8012 * 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.
8013 * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
8014 * \param isQuad specifies the policy of connectivity.
8015 * @ret in/out parameter in which the result will be append
8017 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
8019 INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
8020 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
8021 ret.push_back(cm.getExtrudedType());
8022 int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
8025 case INTERP_KERNEL::NORM_POINT1:
8027 ret.push_back(connBg[1]);
8028 ret.push_back(connBg[1]+nbOfNodesPerLev);
8031 case INTERP_KERNEL::NORM_SEG2:
8033 int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
8034 ret.insert(ret.end(),conn,conn+4);
8037 case INTERP_KERNEL::NORM_SEG3:
8039 int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8040 ret.insert(ret.end(),conn,conn+8);
8043 case INTERP_KERNEL::NORM_QUAD4:
8045 int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8046 ret.insert(ret.end(),conn,conn+8);
8049 case INTERP_KERNEL::NORM_TRI3:
8051 int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8052 ret.insert(ret.end(),conn,conn+6);
8055 case INTERP_KERNEL::NORM_TRI6:
8057 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,
8058 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8059 ret.insert(ret.end(),conn,conn+15);
8062 case INTERP_KERNEL::NORM_QUAD8:
8065 connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8066 connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8067 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8069 ret.insert(ret.end(),conn,conn+20);
8072 case INTERP_KERNEL::NORM_POLYGON:
8074 std::back_insert_iterator< std::vector<int> > ii(ret);
8075 std::copy(connBg+1,connEnd,ii);
8077 std::reverse_iterator<const int *> rConnBg(connEnd);
8078 std::reverse_iterator<const int *> rConnEnd(connBg+1);
8079 std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8080 std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8081 for(std::size_t i=0;i<nbOfRadFaces;i++)
8084 int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8085 std::copy(conn,conn+4,ii);
8090 throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8095 * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8097 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8100 double v[3]={0.,0.,0.};
8101 std::size_t sz=std::distance(begin,end);
8106 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];
8107 v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8108 v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8110 double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8112 // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8113 // SEG3 forming a circle):
8114 if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8116 v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8117 for(std::size_t j=0;j<sz;j++)
8119 if (j%2) // current point i is quadratic, next point i+1 is standard
8122 ip1 = (j+1)%sz; // ip1 = "i+1"
8124 else // current point i is standard, next point i+1 is quadratic
8129 v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8130 v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8131 v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8133 ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8139 * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8141 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8143 std::vector<std::pair<int,int> > edges;
8144 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8145 const int *bgFace=begin;
8146 for(std::size_t i=0;i<nbOfFaces;i++)
8148 const int *endFace=std::find(bgFace+1,end,-1);
8149 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8150 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8152 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8153 if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8155 edges.push_back(p1);
8159 return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8163 * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8165 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8167 double vec0[3],vec1[3];
8168 std::size_t sz=std::distance(begin,end);
8170 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8171 int nbOfNodes=(int)sz/2;
8172 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8173 const double *pt0=coords+3*begin[0];
8174 const double *pt1=coords+3*begin[nbOfNodes];
8175 vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8176 return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8179 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8181 std::size_t sz=std::distance(begin,end);
8182 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8183 std::size_t nbOfNodes(sz/2);
8184 std::copy(begin,end,(int *)tmp);
8185 for(std::size_t j=1;j<nbOfNodes;j++)
8187 begin[j]=tmp[nbOfNodes-j];
8188 begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8192 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8194 std::size_t sz=std::distance(begin,end);
8196 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8197 double vec0[3],vec1[3];
8198 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8199 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];
8200 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;
8203 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8205 std::size_t sz=std::distance(begin,end);
8207 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8209 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8210 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8211 return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8215 * 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 )
8216 * 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
8219 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8220 * \param [in] coords the coordinates with nb of components exactly equal to 3
8221 * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8222 * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8223 * \param [out] res the result is put at the end of the vector without any alteration of the data.
8225 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8227 int nbFaces=std::count(begin+1,end,-1)+1;
8228 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8229 double *vPtr=v->getPointer();
8230 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8231 double *pPtr=p->getPointer();
8232 const int *stFaceConn=begin+1;
8233 for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8235 const int *endFaceConn=std::find(stFaceConn,end,-1);
8236 ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8237 stFaceConn=endFaceConn+1;
8239 pPtr=p->getPointer(); vPtr=v->getPointer();
8240 DataArrayInt *comm1=0,*commI1=0;
8241 v->findCommonTuples(eps,-1,comm1,commI1);
8242 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8243 const int *comm1Ptr=comm1->getConstPointer();
8244 const int *commI1Ptr=commI1->getConstPointer();
8245 int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8246 res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8248 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8249 mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8250 mm->finishInsertingCells();
8252 for(int i=0;i<nbOfGrps1;i++)
8254 int vecId=comm1Ptr[commI1Ptr[i]];
8255 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8256 DataArrayInt *comm2=0,*commI2=0;
8257 tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8258 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8259 const int *comm2Ptr=comm2->getConstPointer();
8260 const int *commI2Ptr=commI2->getConstPointer();
8261 int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8262 for(int j=0;j<nbOfGrps2;j++)
8264 if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8266 res->insertAtTheEnd(begin,end);
8267 res->pushBackSilent(-1);
8271 int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8272 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8273 ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8274 DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8275 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8276 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8277 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8278 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8279 const int *idsNodePtr=idsNode->getConstPointer();
8280 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];
8281 double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8282 double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8283 if(std::abs(norm)>eps)
8285 double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8286 mm3->rotate(center,vec,angle);
8288 mm3->changeSpaceDimension(2);
8289 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8290 const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8291 const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8292 int nbOfCells=mm4->getNumberOfCells();
8293 for(int k=0;k<nbOfCells;k++)
8296 for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8297 res->pushBackSilent(idsNodePtr[*work]);
8298 res->pushBackSilent(-1);
8303 res->popBackSilent();
8307 * 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
8308 * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8310 * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8311 * \param [in] coords coordinates expected to have 3 components.
8312 * \param [in] begin start of the nodal connectivity of the face.
8313 * \param [in] end end of the nodal connectivity (excluded) of the face.
8314 * \param [out] v the normalized vector of size 3
8315 * \param [out] p the pos of plane
8317 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8319 std::size_t nbPoints=std::distance(begin,end);
8321 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8322 double vec[3]={0.,0.,0.};
8324 bool refFound=false;
8325 for(;j<nbPoints-1 && !refFound;j++)
8327 vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8328 vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8329 vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8330 double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8334 vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8337 for(std::size_t i=j;i<nbPoints-1;i++)
8340 curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8341 curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8342 curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8343 double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8346 curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8347 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];
8348 norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8351 v[0]/=norm; v[1]/=norm; v[2]/=norm;
8352 *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8356 throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8360 * This method tries to obtain a well oriented polyhedron.
8361 * If the algorithm fails, an exception will be thrown.
8363 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8365 std::list< std::pair<int,int> > edgesOK,edgesFinished;
8366 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8367 std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8369 int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8370 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8371 for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8373 while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8376 std::size_t smthChanged=0;
8377 for(std::size_t i=0;i<nbOfFaces;i++)
8379 endFace=std::find(bgFace+1,end,-1);
8380 nbOfEdgesInFace=std::distance(bgFace,endFace);
8384 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8386 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8387 std::pair<int,int> p2(p1.second,p1.first);
8388 bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8389 bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8390 if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8395 std::reverse(bgFace+1,endFace);
8396 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8398 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8399 std::pair<int,int> p2(p1.second,p1.first);
8400 if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8401 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8402 if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8403 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8404 std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8405 if(it!=edgesOK.end())
8408 edgesFinished.push_back(p1);
8411 edgesOK.push_back(p1);
8418 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8420 if(!edgesOK.empty())
8421 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8422 if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8423 {//not lucky ! The first face was not correctly oriented : reorient all faces...
8425 for(std::size_t i=0;i<nbOfFaces;i++)
8427 endFace=std::find(bgFace+1,end,-1);
8428 std::reverse(bgFace+1,endFace);
8434 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8436 int nbOfNodesExpected(skin->getNumberOfNodes());
8437 const int *n2oPtr(n2o->getConstPointer());
8438 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8439 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8440 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8441 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8442 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8443 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8444 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_POLYGON;
8445 if(nbOfNodesExpected<1)
8447 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8448 *work++=n2oPtr[prevNode];
8449 for(int i=1;i<nbOfNodesExpected;i++)
8451 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8453 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8454 conn.erase(prevNode);
8457 int curNode(*(conn.begin()));
8458 *work++=n2oPtr[curNode];
8459 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8460 shar.erase(prevCell);
8463 prevCell=*(shar.begin());
8467 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8470 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8473 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8478 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8480 int nbOfNodesExpected(skin->getNumberOfNodes());
8481 int nbOfTurn(nbOfNodesExpected/2);
8482 const int *n2oPtr(n2o->getConstPointer());
8483 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8484 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8485 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8486 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8487 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8488 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8489 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_QPOLYG;
8490 if(nbOfNodesExpected<1)
8492 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8493 *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8494 for(int i=1;i<nbOfTurn;i++)
8496 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8498 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8499 conn.erase(prevNode);
8502 int curNode(*(conn.begin()));
8503 *work=n2oPtr[curNode];
8504 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8505 shar.erase(prevCell);
8508 int curCell(*(shar.begin()));
8509 work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8515 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8518 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8521 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8527 * This method makes the assumption spacedimension == meshdimension == 2.
8528 * This method works only for linear cells.
8530 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8532 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8534 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8535 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8536 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8537 int oldNbOfNodes(skin->getNumberOfNodes());
8538 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8539 int nbOfNodesExpected(skin->getNumberOfNodes());
8540 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8541 int nbCells(skin->getNumberOfCells());
8542 if(nbCells==nbOfNodesExpected)
8543 return buildUnionOf2DMeshLinear(skin,n2o);
8544 else if(2*nbCells==nbOfNodesExpected)
8545 return buildUnionOf2DMeshQuadratic(skin,n2o);
8547 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8551 * This method makes the assumption spacedimension == meshdimension == 3.
8552 * This method works only for linear cells.
8554 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8556 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8558 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8559 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8560 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8561 const int *conn=m->getNodalConnectivity()->getConstPointer();
8562 const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8563 int nbOfCells=m->getNumberOfCells();
8564 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8565 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED;
8568 work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8569 for(int i=1;i<nbOfCells;i++)
8572 work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8578 * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8579 * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8581 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8585 for(int i=0;i<nbOfNodesInCell;i++)
8586 w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8587 else if(spaceDim==2)
8589 for(int i=0;i<nbOfNodesInCell;i++)
8591 w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8596 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8599 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8601 int nbOfCells=getNumberOfCells();
8603 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8604 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};
8605 ofs << " <" << getVTKDataSetType() << ">\n";
8606 ofs << " <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8607 ofs << " <PointData>\n" << pointData << std::endl;
8608 ofs << " </PointData>\n";
8609 ofs << " <CellData>\n" << cellData << std::endl;
8610 ofs << " </CellData>\n";
8611 ofs << " <Points>\n";
8612 if(getSpaceDimension()==3)
8613 _coords->writeVTK(ofs,8,"Points",byteData);
8616 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8617 coo->writeVTK(ofs,8,"Points",byteData);
8619 ofs << " </Points>\n";
8620 ofs << " <Cells>\n";
8621 const int *cPtr=_nodal_connec->getConstPointer();
8622 const int *cIPtr=_nodal_connec_index->getConstPointer();
8623 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8624 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8625 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8626 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8627 int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8628 int szFaceOffsets=0,szConn=0;
8629 for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8632 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8635 *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8636 w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8640 int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8641 *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8642 std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8643 *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8644 w4=std::copy(c.begin(),c.end(),w4);
8647 types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8648 types->writeVTK(ofs,8,"UInt8","types",byteData);
8649 offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8650 if(szFaceOffsets!=0)
8651 {//presence of Polyhedra
8652 connectivity->reAlloc(szConn);
8653 faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8654 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8655 w1=faces->getPointer();
8656 for(int i=0;i<nbOfCells;i++)
8657 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8659 int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8661 const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8662 for(int j=0;j<nbFaces;j++)
8664 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8665 *w1++=(int)std::distance(w6,w5);
8666 w1=std::copy(w6,w5,w1);
8670 faces->writeVTK(ofs,8,"Int32","faces",byteData);
8672 connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8673 ofs << " </Cells>\n";
8674 ofs << " </Piece>\n";
8675 ofs << " </" << getVTKDataSetType() << ">\n";
8678 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8680 stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8682 { stream << " Not set !"; return ; }
8683 stream << " Mesh dimension : " << _mesh_dim << ".";
8687 { stream << " No coordinates set !"; return ; }
8688 if(!_coords->isAllocated())
8689 { stream << " Coordinates set but not allocated !"; return ; }
8690 stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8691 stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8692 if(!_nodal_connec_index)
8693 { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8694 if(!_nodal_connec_index->isAllocated())
8695 { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8696 int lgth=_nodal_connec_index->getNumberOfTuples();
8697 int cpt=_nodal_connec_index->getNumberOfComponents();
8698 if(cpt!=1 || lgth<1)
8700 stream << std::endl << "Number of cells : " << lgth-1 << ".";
8703 std::string MEDCouplingUMesh::getVTKDataSetType() const
8705 return std::string("UnstructuredGrid");
8708 std::string MEDCouplingUMesh::getVTKFileExtension() const
8710 return std::string("vtu");
8714 * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8715 * returns a result mesh constituted by polygons.
8716 * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8717 * all nodes from m2.
8718 * The meshes should be in 2D space. In
8719 * addition, returns two arrays mapping cells of the result mesh to cells of the input
8721 * \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
8722 * 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)
8723 * \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
8724 * 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)
8725 * \param [in] eps - precision used to detect coincident mesh entities.
8726 * \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8727 * cell an id of the cell of \a m1 it comes from. The caller is to delete
8728 * this array using decrRef() as it is no more needed.
8729 * \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8730 * cell an id of the cell of \a m2 it comes from. -1 value means that a
8731 * result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8732 * any cell of \a m2. The caller is to delete this array using decrRef() as
8733 * it is no more needed.
8734 * \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8735 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8736 * is no more needed.
8737 * \throw If the coordinates array is not set in any of the meshes.
8738 * \throw If the nodal connectivity of cells is not defined in any of the meshes.
8739 * \throw If any of the meshes is not a 2D mesh in 2D space.
8741 * \sa conformize2D, mergeNodes
8743 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8744 double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8747 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
8748 m1->checkFullyDefined();
8749 m2->checkFullyDefined();
8750 if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8751 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!");
8753 // Step 1: compute all edge intersections (new nodes)
8754 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8755 MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
8756 DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8757 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
8758 IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
8759 m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8760 addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
8761 revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8762 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8763 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8765 // Step 2: re-order newly created nodes according to the ordering found in m2
8766 std::vector< std::vector<int> > intersectEdge2;
8767 BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8768 subDiv2.clear(); dd5=0; dd6=0;
8771 std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8772 std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8773 BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8774 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8776 // Step 4: Prepare final result:
8777 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
8778 addCooDa->alloc((int)(addCoo.size())/2,2);
8779 std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8780 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
8781 addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8782 std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8783 std::vector<const DataArrayDouble *> coordss(4);
8784 coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8785 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
8786 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
8787 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8788 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8789 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8790 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8791 ret->setConnectivity(conn,connI,true);
8792 ret->setCoords(coo);
8793 cellNb1=c1.retn(); cellNb2=c2.retn();
8799 bool IsColinearOfACellOf(const std::vector< std::vector<int> >& intersectEdge1, const std::vector<int>& candidates, int start, int stop, int& retVal)
8801 if(candidates.empty())
8803 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
8805 const std::vector<int>& pool(intersectEdge1[*it]);
8806 int tmp[2]; tmp[0]=start; tmp[1]=stop;
8807 if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
8812 tmp[0]=stop; tmp[1]=start;
8813 if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
8822 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,
8823 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInRetColinear, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInMesh1DForIdsInRetColinear)
8825 idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1);
8826 idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1);
8827 int nCells(mesh1D->getNumberOfCells());
8828 if(nCells!=(int)intersectEdge2.size())
8829 throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
8830 const DataArrayDouble *coo2(mesh1D->getCoords());
8831 const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
8832 const double *coo2Ptr(coo2->begin());
8833 int offset1(coords1->getNumberOfTuples());
8834 int offset2(offset1+coo2->getNumberOfTuples());
8835 int offset3(offset2+addCoo.size()/2);
8836 std::vector<double> addCooQuad;
8837 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
8838 int tmp[4],cicnt(0),kk(0);
8839 for(int i=0;i<nCells;i++)
8841 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
8842 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
8843 const std::vector<int>& subEdges(intersectEdge2[i]);
8844 int nbSubEdge(subEdges.size()/2);
8845 for(int j=0;j<nbSubEdge;j++,kk++)
8847 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));
8848 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
8849 INTERP_KERNEL::Edge *e2Ptr(e2);
8850 std::map<int,int>::const_iterator itm;
8851 if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
8853 tmp[0]=INTERP_KERNEL::NORM_SEG3;
8854 itm=mergedNodes.find(subEdges[2*j]);
8855 tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
8856 itm=mergedNodes.find(subEdges[2*j+1]);
8857 tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
8858 tmp[3]=offset3+(int)addCooQuad.size()/2;
8860 e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2);
8862 cOut->insertAtTheEnd(tmp,tmp+4);
8863 ciOut->pushBackSilent(cicnt);
8867 tmp[0]=INTERP_KERNEL::NORM_SEG2;
8868 itm=mergedNodes.find(subEdges[2*j]);
8869 tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
8870 itm=mergedNodes.find(subEdges[2*j+1]);
8871 tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
8873 cOut->insertAtTheEnd(tmp,tmp+3);
8874 ciOut->pushBackSilent(cicnt);
8877 if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00))
8879 idsInRetColinear->pushBackSilent(kk);
8880 idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00);
8885 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
8886 ret->setConnectivity(cOut,ciOut,true);
8887 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr3(DataArrayDouble::New());
8888 arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
8889 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
8890 std::vector<const DataArrayDouble *> coordss(4);
8891 coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
8892 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
8893 ret->setCoords(arr);
8897 MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
8899 std::vector<int> allEdges;
8900 for(const int *it2(descBg);it2!=descEnd;it2++)
8902 const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
8904 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
8906 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
8908 std::size_t nb(allEdges.size());
8910 throw INTERP_KERNEL::Exception("BuildRefined2DCell : internal error 1 !");
8911 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
8912 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
8913 ret->setCoords(coords);
8914 ret->allocateCells(1);
8915 std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
8916 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
8917 connOut[kk]=allEdges[2*kk];
8918 ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]);
8922 void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector<int>& conn, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edges)
8925 for(std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >::const_iterator it=edges.begin();it!=edges.end();it++)
8927 const INTERP_KERNEL::Edge *ee(*it);
8928 if(dynamic_cast<const INTERP_KERNEL::EdgeArcCircle *>(ee))
8932 mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]);
8935 const double *coo(mesh2D->getCoords()->begin());
8936 std::size_t sz(conn.size());
8937 std::vector<double> addCoo;
8938 std::vector<int> conn2(conn);
8939 int offset(mesh2D->getNumberOfNodes());
8940 for(std::size_t i=0;i<sz;i++)
8943 edges[(i+1)%sz]->getMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);
8944 addCoo.insert(addCoo.end(),tmp,tmp+2);
8945 conn2.push_back(offset+(int)i);
8947 mesh2D->getCoords()->rearrange(1);
8948 mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size());
8949 mesh2D->getCoords()->rearrange(2);
8950 mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]);
8955 * \b WARNING edges in out1 coming from \a splitMesh1D are \b NOT oriented because only used for equation of curve.
8957 void BuildMesh2DCutInternal2(const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& edge1Bis, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edge1BisPtr,
8958 std::vector< std::vector<int> >& out0, std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& out1)
8960 std::size_t nb(edge1Bis.size()/2);
8961 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
8962 int iEnd(splitMesh1D->getNumberOfCells());
8964 throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal2 : internal error ! input 1D mesh must have at least one cell !");
8966 const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
8967 for(ii=0;ii<nb && edge1Bis[2*ii]!=cSplitPtr[ciSplitPtr[0]+1];ii++);
8968 for(jj=ii;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd-1]+2];jj++);
8971 {//the edges splitMesh1D[iStart:iEnd] does not fully cut the current 2D cell -> single output cell
8972 out0.resize(1); out1.resize(1);
8973 std::vector<int>& connOut(out0[0]);
8974 connOut.resize(nbOfEdgesOf2DCellSplit);
8975 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr(out1[0]);
8976 edgesPtr.resize(nbOfEdgesOf2DCellSplit);
8977 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
8979 connOut[kk]=edge1Bis[2*kk];
8980 edgesPtr[kk]=edge1BisPtr[2*kk];
8985 // [i,iEnd[ contains the
8986 out0.resize(2); out1.resize(2);
8987 std::vector<int>& connOutLeft(out0[0]);
8988 std::vector<int>& connOutRight(out0[1]);//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1]
8989 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eleft(out1[0]);
8990 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eright(out1[1]);
8991 for(std::size_t k=ii;k<jj+1;k++)
8992 { connOutLeft.push_back(edge1Bis[2*k+1]); eleft.push_back(edge1BisPtr[2*k+1]); }
8993 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > ees(iEnd);
8994 for(int ik=iEnd-1;ik>=0;ik--)
8996 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
8997 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9000 for(int ik=iEnd-1;ik>=0;ik--)
9001 connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]);
9002 for(std::size_t k=jj+1;k<nbOfEdgesOf2DCellSplit+ii;k++)
9003 { connOutRight.push_back(edge1Bis[2*k+1]); eright.push_back(edge1BisPtr[2*k+1]); }
9004 eleft.insert(eleft.end(),ees.begin(),ees.end());
9005 for(int ik=0;ik<iEnd;ik++)
9006 connOutRight.push_back(cSplitPtr[ciSplitPtr[ik]+2]);
9007 eright.insert(eright.end(),ees.rbegin(),ees.rend());
9019 CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9021 std::vector<int> _edges;
9022 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > _edges_ptr;
9025 CellInfo::CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr)
9027 std::size_t nbe(edges.size());
9028 std::vector<int> edges2(2*nbe); std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edgesPtr2(2*nbe);
9029 for(std::size_t i=0;i<nbe;i++)
9031 edges2[2*i]=edges[i]; edges2[2*i+1]=edges[(i+1)%nbe];
9032 edgesPtr2[2*i]=edgesPtr[i]; edgesPtr2[2*i+1]=edgesPtr[i];
9034 _edges.resize(4*nbe); _edges_ptr.resize(4*nbe);
9035 std::copy(edges2.begin(),edges2.end(),_edges.begin()); std::copy(edges2.begin(),edges2.end(),_edges.begin()+2*nbe);
9036 std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()); std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()+2*nbe);
9042 EdgeInfo(int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh):_istart(istart),_iend(iend),_mesh(mesh),_left(-7),_right(-7) { }
9043 EdgeInfo(int istart, int iend, int pos, const MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge>& edge):_istart(istart),_iend(iend),_edge(edge),_left(pos),_right(pos+1) { }
9044 bool isInMyRange(int pos) const { return pos>=_istart && pos<_iend; }
9045 void somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9046 void feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const;
9050 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _mesh;
9051 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> _edge;
9056 void EdgeInfo::somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9058 const MEDCouplingUMesh *mesh(_mesh);
9064 { _left++; _right++; return ; }
9067 bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9068 if((isLeft && isRight) || (!isLeft && !isRight))
9069 throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 1 !");
9080 bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9081 if((isLeft && isRight) || (!isLeft && !isRight))
9082 throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 2 !");
9097 void EdgeInfo::feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const
9099 const MEDCouplingUMesh *mesh(_mesh);
9102 neighbors[0]=offset+_left; neighbors[1]=offset+_right;
9105 {// not fully splitting cell case
9106 if(mesh2D->getNumberOfCells()==1)
9107 {//little optimization. 1 cell no need to find in which cell mesh is !
9108 neighbors[0]=offset; neighbors[1]=offset;
9113 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9114 int cellId(mesh2D->getCellContainingPoint(barys->begin(),eps));
9116 throw INTERP_KERNEL::Exception("EdgeInfo::feedEdgeInfoAt : internal error !");
9117 neighbors[0]=offset+cellId; neighbors[1]=offset+cellId;
9122 class VectorOfCellInfo
9125 VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9126 std::size_t size() const { return _pool.size(); }
9127 int getPositionOf(double eps, const MEDCouplingUMesh *mesh) const;
9128 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);
9129 const std::vector<int>& getConnOf(int pos) const { return get(pos)._edges; }
9130 const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& getEdgePtrOf(int pos) const { return get(pos)._edges_ptr; }
9131 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> getZeMesh() const { return _ze_mesh; }
9132 void feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const;
9134 int getZePosOfEdgeGivenItsGlobalId(int pos) const;
9135 void updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9136 const CellInfo& get(int pos) const;
9137 CellInfo& get(int pos);
9139 std::vector<CellInfo> _pool;
9140 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _ze_mesh;
9141 std::vector<EdgeInfo> _edge_info;
9144 VectorOfCellInfo::VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr):_pool(1)
9146 _pool[0]._edges=edges;
9147 _pool[0]._edges_ptr=edgesPtr;
9150 int VectorOfCellInfo::getPositionOf(double eps, const MEDCouplingUMesh *mesh) const
9153 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : empty !");
9156 const MEDCouplingUMesh *zeMesh(_ze_mesh);
9158 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : null aggregated mesh !");
9159 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9160 return zeMesh->getCellContainingPoint(barys->begin(),eps);
9163 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)
9165 get(pos);//to check pos
9166 bool isFast(pos==0 && _pool.size()==1);
9167 std::size_t sz(edges.size());
9168 // dealing with edges
9170 _edge_info.push_back(EdgeInfo(istart,iend,mesh1DInCase));
9172 _edge_info.push_back(EdgeInfo(istart,iend,pos,edgePtrs[0].back()));
9174 std::vector<CellInfo> pool(_pool.size()-1+sz);
9175 for(int i=0;i<pos;i++)
9177 for(std::size_t j=0;j<sz;j++)
9178 pool[pos+j]=CellInfo(edges[j],edgePtrs[j]);
9179 for(int i=pos+1;i<(int)_pool.size();i++)
9180 pool[pos+sz-1]=_pool[i];
9184 updateEdgeInfo(pos,edgePtrs[0],edgePtrs[1]);
9192 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > ms;
9195 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(0,pos,true)));
9199 if(pos<_ze_mesh->getNumberOfCells()-1)
9201 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(pos+1,_ze_mesh->getNumberOfCells(),true)));
9204 std::vector< const MEDCouplingUMesh *> ms2(ms.size());
9205 for(std::size_t j=0;j<ms2.size();j++)
9207 _ze_mesh=MEDCouplingUMesh::MergeUMeshesOnSameCoords(ms2);
9210 void VectorOfCellInfo::feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const
9212 _edge_info[getZePosOfEdgeGivenItsGlobalId(pos)].feedEdgeInfoAt(eps,_ze_mesh,offset,neighbors);
9215 int VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId(int pos) const
9218 throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id ! Must be >=0 !");
9220 for(std::vector<EdgeInfo>::const_iterator it=_edge_info.begin();it!=_edge_info.end();it++,ret++)
9222 if((*it).isInMyRange(pos))
9225 throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id !");
9228 void VectorOfCellInfo::updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9230 get(pos);//to check;
9231 if(_edge_info.empty())
9233 std::size_t sz(_edge_info.size()-1);
9234 for(std::size_t i=0;i<sz;i++)
9235 _edge_info[i].somethingHappendAt(pos,newLeft,newRight);
9238 const CellInfo& VectorOfCellInfo::get(int pos) const
9240 if(pos<0 || pos>=(int)_pool.size())
9241 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get const : invalid pos !");
9245 CellInfo& VectorOfCellInfo::get(int pos)
9247 if(pos<0 || pos>=(int)_pool.size())
9248 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get : invalid pos !");
9252 MEDCouplingUMesh *BuildMesh2DCutInternal(double eps, const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& allEdges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& allEdgesPtr, int offset,
9253 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9255 int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells());
9256 if(nbCellsInSplitMesh1D==0)
9257 throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal : internal error ! input 1D mesh must have at least one cell !");
9258 const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9259 std::size_t nb(allEdges.size()),jj;
9261 throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !");
9262 std::vector<int> edge1Bis(nb*2);
9263 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edge1BisPtr(nb*2);
9264 std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin());
9265 std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb);
9266 std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin());
9267 std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb);
9269 idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(nbCellsInSplitMesh1D*2); idsLeftRight->fillWithValue(-2); idsLeftRight->rearrange(2);
9270 int *idsLeftRightPtr(idsLeftRight->getPointer());
9271 VectorOfCellInfo pool(edge1Bis,edge1BisPtr);
9272 for(int iStart=0;iStart<nbCellsInSplitMesh1D;)
9273 {// split [0:nbCellsInSplitMesh1D) in contiguous parts [iStart:iEnd)
9275 for(;iEnd<nbCellsInSplitMesh1D;)
9277 for(jj=0;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd]+2];jj++);
9283 if(iEnd<nbCellsInSplitMesh1D)
9286 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfSplitMesh1D(static_cast<MEDCouplingUMesh *>(splitMesh1D->buildPartOfMySelf2(iStart,iEnd,1,true)));
9287 int pos(pool.getPositionOf(eps,partOfSplitMesh1D));
9289 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>retTmp(MEDCouplingUMesh::New("",2));
9290 retTmp->setCoords(splitMesh1D->getCoords());
9291 retTmp->allocateCells();
9293 std::vector< std::vector<int> > out0;
9294 std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > > out1;
9296 BuildMesh2DCutInternal2(partOfSplitMesh1D,pool.getConnOf(pos),pool.getEdgePtrOf(pos),out0,out1);
9297 for(std::size_t cnt=0;cnt<out0.size();cnt++)
9298 AddCellInMesh2D(retTmp,out0[cnt],out1[cnt]);
9299 pool.setMeshAt(pos,retTmp,iStart,iEnd,partOfSplitMesh1D,out0,out1);
9303 for(int mm=0;mm<nbCellsInSplitMesh1D;mm++)
9304 pool.feedEdgeInfoAt(eps,mm,offset,idsLeftRightPtr+2*mm);
9305 return pool.getZeMesh().retn();
9308 MEDCouplingUMesh *BuildMesh2DCutFrom(double eps, int cellIdInMesh2D, const MEDCouplingUMesh *mesh2DDesc, const MEDCouplingUMesh *splitMesh1D,
9309 const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1, int offset,
9310 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9312 const int *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin());
9314 std::vector<int> allEdges;
9315 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > allEdgesPtr;
9316 for(const int *it(descBg);it!=descEnd;it++)
9318 int edgeId(std::abs(*it)-1);
9319 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9320 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m));
9321 const std::vector<int>& edge1(intersectEdge1[edgeId]);
9323 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9325 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9326 std::size_t sz(edge1.size());
9327 for(std::size_t cnt=0;cnt<sz;cnt++)
9328 allEdgesPtr.push_back(ee);
9331 return BuildMesh2DCutInternal(eps,splitMesh1D,allEdges,allEdgesPtr,offset,idsLeftRight);
9337 * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
9338 * 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
9339 * and finaly, in case of quadratic polygon the centers of edges new nodes.
9340 * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
9342 * \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
9343 * 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)
9344 * \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
9345 * you can invoke orderConsecutiveCells1D on \a mesh1D.
9346 * \param [in] eps - precision used to perform intersections and localization operations.
9347 * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
9348 * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
9349 * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
9350 * 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.
9351 * \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
9352 * and the cell in \a splitMesh2D on the right for the 2nt component. -1 means no cell.
9353 * 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.
9355 * \sa Intersect2DMeshes, orderConsecutiveCells1D, conformize2D, mergeNodes
9357 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
9359 if(!mesh2D || !mesh1D)
9360 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
9361 mesh2D->checkFullyDefined();
9362 mesh1D->checkFullyDefined();
9363 const std::vector<std::string>& compNames(mesh2D->getCoords()->getInfoOnComponents());
9364 if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
9365 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
9366 // Step 1: compute all edge intersections (new nodes)
9367 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9368 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
9369 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9370 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9372 // Build desc connectivity
9373 DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
9374 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9375 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
9376 std::map<int,int> mergedNodes;
9377 Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes);
9378 // use mergeNodes to fix intersectEdge1
9379 for(std::vector< std::vector<int> >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++)
9381 std::size_t n((*it0).size()/2);
9382 int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]);
9383 std::map<int,int>::const_iterator it1;
9384 it1=mergedNodes.find(eltStart);
9385 if(it1!=mergedNodes.end())
9386 (*it0)[0]=(*it1).second;
9387 it1=mergedNodes.find(eltEnd);
9388 if(it1!=mergedNodes.end())
9389 (*it0)[2*n-1]=(*it1).second;
9392 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9393 addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9394 // Step 2: re-order newly created nodes according to the ordering found in m2
9395 std::vector< std::vector<int> > intersectEdge2;
9396 BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
9398 // Step 3: compute splitMesh1D
9399 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear;
9400 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2(DataArrayInt::New()); ret2->alloc(0,1);
9401 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1,
9402 idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear));
9403 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(-1); ret3->rearrange(2);
9404 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells()));
9405 // deal with cells in mesh2D that are not cut but only some of their edges are
9406 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCpy());
9407 idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1);
9408 idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique();
9409 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
9410 if(!idsInDesc2DToBeRefined->empty())
9412 DataArrayInt *out0(0),*outi0(0);
9413 MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
9414 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> outi0s(outi0);
9416 out0s=out0s->buildUnique();
9420 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1NonCol(static_cast<MEDCouplingUMesh *>(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end())));
9421 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> baryRet1(ret1NonCol->getBarycenterAndOwner());
9422 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elts,eltsIndex;
9423 mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
9424 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex2(eltsIndex->deltaShiftIndex());
9425 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex3(eltsIndex2->getIdsEqual(1));
9426 if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells())
9427 throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !");
9428 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToBeModified(elts->buildUnique());
9429 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells()));
9430 if((DataArrayInt *)out0s)
9431 untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one
9432 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > outMesh2DSplit;
9433 // OK all is ready to insert in ret2 mesh
9434 if(!untouchedCells->empty())
9435 {// the most easy part, cells in mesh2D not impacted at all
9436 outMesh2DSplit.push_back(static_cast<MEDCouplingUMesh *>(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end())));
9437 outMesh2DSplit.back()->setCoords(ret1->getCoords());
9438 ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end());
9440 if((DataArrayInt *)out0s)
9441 {// here dealing with cells in out0s but not in cellsToBeModified
9442 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fewModifiedCells(out0s->buildSubstraction(cellsToBeModified));
9443 const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin());
9444 for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++)
9446 outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1));
9448 int offset(ret2->getNumberOfTuples());
9449 ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end());
9450 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1);
9451 partOfRet3->fillWithValue(-1); partOfRet3->rearrange(2);
9452 int kk(0),*ret3ptr(partOfRet3->getPointer());
9453 for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++)
9455 int faceId(std::abs(*it)-1);
9456 for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++)
9458 int tmp(fewModifiedCells->locateValue(*it2));
9461 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9462 ret3ptr[2*kk]=tmp+offset;
9463 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9464 ret3ptr[2*kk+1]=tmp+offset;
9467 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : internal error 1 !");
9470 ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true);
9472 for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++)
9474 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell(elts->getIdsEqual(*it));
9475 idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end());
9476 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end()));
9477 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfMesh1CuttingCur2DCell(static_cast<MEDCouplingUMesh *>(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end())));
9478 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3;
9479 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));
9480 ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true);
9481 outMesh2DSplit.push_back(splitOfOneCell);
9482 for(int i=0;i<splitOfOneCell->getNumberOfCells();i++)
9483 ret2->pushBackSilent(*it);
9486 std::size_t nbOfMeshes(outMesh2DSplit.size());
9487 std::vector<const MEDCouplingUMesh *> tmp(nbOfMeshes);
9488 for(std::size_t i=0;i<nbOfMeshes;i++)
9489 tmp[i]=outMesh2DSplit[i];
9491 ret1->getCoords()->setInfoOnComponents(compNames);
9493 splitMesh1D=ret1.retn();
9494 splitMesh2D=MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp);
9495 cellIdInMesh2D=ret2.retn();
9496 cellIdInMesh1D=ret3.retn();
9500 * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
9501 * (newly created) nodes corresponding to the edge intersections.
9503 * @param[out] cr, crI connectivity of the resulting mesh
9504 * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
9505 * TODO: describe input parameters
9507 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
9508 const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
9509 const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
9510 const std::vector<double>& addCoords,
9511 std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
9513 static const int SPACEDIM=2;
9514 const double *coo1(m1->getCoords()->getConstPointer());
9515 const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer());
9516 int offset1(m1->getNumberOfNodes());
9517 const double *coo2(m2->getCoords()->getConstPointer());
9518 const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer());
9519 int offset2(offset1+m2->getNumberOfNodes());
9520 int offset3(offset2+((int)addCoords.size())/2);
9521 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
9522 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9523 // Here a BBTree on 2D-cells, not on segments:
9524 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
9525 int ncell1(m1->getNumberOfCells());
9527 for(int i=0;i<ncell1;i++)
9529 std::vector<int> candidates2;
9530 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9531 std::map<INTERP_KERNEL::Node *,int> mapp;
9532 std::map<int,INTERP_KERNEL::Node *> mappRev;
9533 INTERP_KERNEL::QuadraticPolygon pol1;
9534 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
9535 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
9536 // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
9537 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
9538 // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
9539 pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
9540 desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
9542 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
9543 std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
9544 INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
9545 for(it1.first();!it1.finished();it1.next())
9546 edges1.insert(it1.current()->getPtr());
9548 std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
9549 std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
9551 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9553 INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
9554 const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
9555 // Complete mapping with elements coming from the current cell it2 in mesh2:
9556 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
9557 // pol2 is the new QP in the final merged result.
9558 pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
9559 pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
9562 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9564 INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
9565 pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
9566 //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
9567 pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9569 // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
9570 // by m2 but that we still want to keep in the final result.
9575 INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9577 catch(INTERP_KERNEL::Exception& e)
9579 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();
9580 throw INTERP_KERNEL::Exception(oss.str().c_str());
9583 for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
9584 (*it).second->decrRef();
9589 * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
9590 * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
9591 * This doesn't modify the mesh.
9592 * The caller is to deal with the resulting DataArrayInt.
9593 * \throw If the coordinate array is not set.
9594 * \throw If the nodal connectivity of the cells is not defined.
9595 * \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
9596 * \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
9598 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
9600 checkFullyDefined();
9601 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
9602 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with (meshdim, spacedim) = (1,2)!");
9604 // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
9605 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
9606 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
9607 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
9608 const int *d(_d->getConstPointer()), *dI(_dI->getConstPointer());
9609 const int *rD(_rD->getConstPointer()), *rDI(_rDI->getConstPointer());
9610 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
9611 const int * dsi(_dsi->getConstPointer());
9612 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dsii = _dsi->getIdsNotInRange(0,3);
9614 if (dsii->getNumberOfTuples())
9615 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
9617 int nc(getNumberOfCells());
9618 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> result(DataArrayInt::New());
9619 result->alloc(nc,1);
9621 // set of edges not used so far
9622 std::set<int> edgeSet;
9623 for (int i=0; i<nc; edgeSet.insert(i), i++);
9627 // while we have points with only one neighbor segments
9630 std::list<int> linePiece;
9631 // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
9632 for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
9634 // Fill the list forward (resp. backward) from the start segment:
9635 int activeSeg = startSeg;
9636 int prevPointId = -20;
9638 while (!edgeSet.empty())
9640 if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
9643 linePiece.push_back(activeSeg);
9645 linePiece.push_front(activeSeg);
9646 edgeSet.erase(activeSeg);
9649 int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
9650 ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
9651 if (dsi[ptId] == 1) // hitting the end of the line
9654 int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
9655 activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
9658 // Done, save final piece into DA:
9659 std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
9660 newIdx += linePiece.size();
9662 // identify next valid start segment (one which is not consumed)
9663 if(!edgeSet.empty())
9664 startSeg = *(edgeSet.begin());
9666 while (!edgeSet.empty());
9667 return result.retn();
9672 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
9674 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> nTmp(n); nTmp->incrRef();
9675 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>::const_iterator it(m.find(nTmp));
9677 throw INTERP_KERNEL::Exception("Internal error in remapping !");
9678 int v((*it).second);
9679 if(v==forbVal0 || v==forbVal1)
9681 if(std::find(isect.begin(),isect.end(),v)==isect.end())
9685 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
9690 bool presenceOfOn(false);
9691 for(int i=0;i<sz;i++)
9693 INTERP_KERNEL::ElementaryEdge *e(c[i]);
9694 if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
9696 IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
9697 IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
9699 return presenceOfOn;
9705 * 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.
9706 * 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.
9707 * 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.
9708 * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to avoid to have a non conform mesh.
9710 * \return int - the number of new nodes created (in most of cases 0).
9712 * \throw If \a this is not coherent.
9713 * \throw If \a this has not spaceDim equal to 2.
9714 * \throw If \a this has not meshDim equal to 2.
9715 * \throw If some subcells needed to be split are orphan.
9716 * \sa MEDCouplingUMesh::conformize2D
9718 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
9720 if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
9721 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
9722 desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
9723 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
9724 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
9725 if(midOpt==0 && midOptI==0)
9727 split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
9730 else if(midOpt!=0 && midOptI!=0)
9731 return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
9733 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
9737 * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
9738 * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
9739 * 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
9740 * 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).
9741 * 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.
9743 * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
9744 * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
9746 * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
9747 * This method expects that all nodes in \a this are not closer than \a eps.
9748 * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
9750 * \param [in] eps the relative error to detect merged edges.
9751 * \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
9752 * that the user is expected to deal with.
9754 * \throw If \a this is not coherent.
9755 * \throw If \a this has not spaceDim equal to 2.
9756 * \throw If \a this has not meshDim equal to 2.
9757 * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
9759 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
9761 static const int SPACEDIM=2;
9763 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
9764 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
9765 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
9766 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
9767 const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
9768 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
9769 const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
9770 int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
9771 std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
9772 std::vector<double> addCoo;
9773 BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
9774 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9775 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9776 for(int i=0;i<nDescCell;i++)
9778 std::vector<int> candidates;
9779 myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
9780 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
9783 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9784 INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
9785 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
9786 INTERP_KERNEL::MergePoints merge;
9787 INTERP_KERNEL::QuadraticPolygon c1,c2;
9788 e1->intersectWith(e2,merge,c1,c2);
9789 e1->decrRef(); e2->decrRef();
9790 if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
9791 overlapEdge[i].push_back(*it);
9792 if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
9793 overlapEdge[*it].push_back(i);
9796 // splitting done. sort intersect point in intersectEdge.
9797 std::vector< std::vector<int> > middle(nDescCell);
9798 int nbOf2DCellsToBeSplit(0);
9799 bool middleNeedsToBeUsed(false);
9800 std::vector<bool> cells2DToTreat(nDescCell,false);
9801 for(int i=0;i<nDescCell;i++)
9803 std::vector<int>& isect(intersectEdge[i]);
9804 int sz((int)isect.size());
9807 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9808 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
9809 e->sortSubNodesAbs(coords,isect);
9814 int idx0(rdi[i]),idx1(rdi[i+1]);
9816 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
9817 if(!cells2DToTreat[rd[idx0]])
9819 cells2DToTreat[rd[idx0]]=true;
9820 nbOf2DCellsToBeSplit++;
9822 // try to reuse at most eventual 'middle' of SEG3
9823 std::vector<int>& mid(middle[i]);
9824 mid.resize(sz+1,-1);
9825 if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
9827 middleNeedsToBeUsed=true;
9828 const std::vector<int>& candidates(overlapEdge[i]);
9829 std::vector<int> trueCandidates;
9830 for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
9831 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
9832 trueCandidates.push_back(*itc);
9833 int stNode(c[ci[i]+1]),endNode(isect[0]);
9834 for(int j=0;j<sz+1;j++)
9836 for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
9838 int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
9839 if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
9840 { mid[j]=*itc; break; }
9843 endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
9848 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
9849 if(nbOf2DCellsToBeSplit==0)
9852 int *retPtr(ret->getPointer());
9853 for(int i=0;i<nCell;i++)
9854 if(cells2DToTreat[i])
9857 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
9858 DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
9859 MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
9860 DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
9861 if(middleNeedsToBeUsed)
9862 { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
9863 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
9864 int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
9865 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.
9866 setPartOfMySelf(ret->begin(),ret->end(),*modif);
9868 bool areNodesMerged; int newNbOfNodes;
9869 if(nbOfNodesCreated!=0)
9870 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
9876 * 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.
9877 * 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).
9878 * 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
9879 * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
9880 * 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
9881 * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
9883 * 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
9884 * using new instance, idem for coordinates.
9886 * 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.
9888 * \return DataArrayInt * - The list of cellIds in \a this that have at least one edge colinearized.
9890 * \throw If \a this is not coherent.
9891 * \throw If \a this has not spaceDim equal to 2.
9892 * \throw If \a this has not meshDim equal to 2.
9894 * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
9896 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
9898 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
9900 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
9901 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
9902 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9903 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9904 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
9905 const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
9906 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
9907 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
9908 const double *coords(_coords->begin());
9909 int *newciptr(newci->getPointer());
9910 for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
9912 if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
9913 ret->pushBackSilent(i);
9914 newciptr[1]=newc->getNumberOfTuples();
9919 if(!appendedCoords->empty())
9921 appendedCoords->rearrange(2);
9922 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
9924 setCoords(newCoords);
9927 setConnectivity(newc,newci,true);
9932 * \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.
9933 * 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.
9934 * And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
9935 * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
9936 * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
9937 * \param [out] addCoo - nodes to be append at the end
9938 * \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.
9940 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
9941 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)
9943 static const int SPACEDIM=2;
9944 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9945 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9946 const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer());
9947 // Build BB tree of all edges in the tool mesh (second mesh)
9948 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
9949 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9950 int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
9951 intersectEdge1.resize(nDescCell1);
9952 colinear2.resize(nDescCell2);
9953 subDiv2.resize(nDescCell2);
9954 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
9956 std::vector<int> candidates1(1);
9957 int offset1(m1Desc->getNumberOfNodes());
9958 int offset2(offset1+m2Desc->getNumberOfNodes());
9959 for(int i=0;i<nDescCell1;i++) // for all edges in the first mesh
9961 std::vector<int> candidates2; // edges of mesh2 candidate for intersection
9962 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9963 if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
9965 std::map<INTERP_KERNEL::Node *,int> map1,map2;
9966 // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
9967 INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
9969 INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
9970 // 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
9971 // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
9972 std::set<INTERP_KERNEL::Node *> nodes;
9973 pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
9974 std::size_t szz(nodes.size());
9975 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
9976 std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
9977 for(std::size_t iii=0;iii<szz;iii++,itt++)
9978 { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
9979 // end of protection
9980 // Performs egde cutting:
9981 pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes);
9986 intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
9991 * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
9992 * It builds the descending connectivity of the two meshes, and then using a binary tree
9993 * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
9994 * Documentation about parameters colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
9996 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
9997 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
9998 MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
9999 std::vector<double>& addCoo,
10000 MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
10002 // Build desc connectivity
10003 desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
10004 desc2=DataArrayInt::New();
10005 descIndx2=DataArrayInt::New();
10006 revDesc2=DataArrayInt::New();
10007 revDescIndx2=DataArrayInt::New();
10008 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
10009 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
10010 m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
10011 m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
10012 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
10013 std::map<int,int> notUsedMap;
10014 Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap);
10015 m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
10016 m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
10020 * This method performs the 2nd step of Partition of 2D mesh.
10021 * This method has 4 inputs :
10022 * - a mesh 'm1' with meshDim==1 and a SpaceDim==2
10023 * - a mesh 'm2' with meshDim==1 and a SpaceDim==2
10024 * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
10025 * 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'
10026 * Nodes end up lying consecutively on a cutted edge.
10027 * \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.
10028 * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
10029 * \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.
10030 * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
10031 * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
10033 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
10034 const std::vector<double>& addCoo,
10035 const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
10037 int offset1=m1->getNumberOfNodes();
10038 int ncell=m2->getNumberOfCells();
10039 const int *c=m2->getNodalConnectivity()->getConstPointer();
10040 const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
10041 const double *coo=m2->getCoords()->getConstPointer();
10042 const double *cooBis=m1->getCoords()->getConstPointer();
10043 int offset2=offset1+m2->getNumberOfNodes();
10044 intersectEdge.resize(ncell);
10045 for(int i=0;i<ncell;i++,cI++)
10047 const std::vector<int>& divs=subDiv[i];
10048 int nnode=cI[1]-cI[0]-1;
10049 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
10050 std::map<INTERP_KERNEL::Node *, int> mapp22;
10051 for(int j=0;j<nnode;j++)
10053 INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
10054 int nnid=c[(*cI)+j+1];
10055 mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
10056 mapp22[nn]=nnid+offset1;
10058 INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
10059 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
10060 ((*it).second.first)->decrRef();
10061 std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
10062 std::map<INTERP_KERNEL::Node *,int> mapp3;
10063 for(std::size_t j=0;j<divs.size();j++)
10066 INTERP_KERNEL::Node *tmp=0;
10068 tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
10069 else if(id<offset2)
10070 tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
10072 tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
10076 e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
10077 for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
10084 * 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).
10085 * 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
10086 * with a plane. The result will be put in 'cut3DSuf' out parameter.
10087 * \param [in] cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
10088 * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
10089 * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
10090 * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
10091 * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
10092 * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
10093 * \param [in] desc is the descending connectivity 3DSurf->3DCurve
10094 * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
10095 * \param [out] cut3DSuf input/output param.
10097 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
10098 const int *nodal3DCurve, const int *nodalIndx3DCurve,
10099 const int *desc, const int *descIndx,
10100 std::vector< std::pair<int,int> >& cut3DSurf)
10102 std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
10103 int nbOf3DSurfCell=(int)cut3DSurf.size();
10104 for(int i=0;i<nbOf3DSurfCell;i++)
10106 std::vector<int> res;
10107 int offset=descIndx[i];
10108 int nbOfSeg=descIndx[i+1]-offset;
10109 for(int j=0;j<nbOfSeg;j++)
10111 int edgeId=desc[offset+j];
10112 int status=cut3DCurve[edgeId];
10116 res.push_back(status);
10119 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
10120 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
10128 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10134 std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
10135 std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
10138 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10142 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
10147 {// case when plane is on a multi colinear edge of a polyhedron
10148 if((int)res.size()==2*nbOfSeg)
10150 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
10153 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
10160 * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
10161 * 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).
10162 * 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
10163 * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
10164 * \param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
10165 * \param desc is the descending connectivity 3D->3DSurf
10166 * \param descIndx is the descending connectivity index 3D->3DSurf
10168 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
10169 const int *desc, const int *descIndx,
10170 DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
10172 checkFullyDefined();
10173 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10174 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
10175 const int *nodal3D=_nodal_connec->getConstPointer();
10176 const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
10177 int nbOfCells=getNumberOfCells();
10178 for(int i=0;i<nbOfCells;i++)
10180 std::map<int, std::set<int> > m;
10181 int offset=descIndx[i];
10182 int nbOfFaces=descIndx[i+1]-offset;
10185 for(int j=0;j<nbOfFaces;j++)
10187 const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
10188 if(p.first!=-1 && p.second!=-1)
10192 start=p.first; end=p.second;
10193 m[p.first].insert(p.second);
10194 m[p.second].insert(p.first);
10198 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
10199 int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
10200 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
10201 INTERP_KERNEL::NormalizedCellType cmsId;
10202 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
10203 start=tmp[0]; end=tmp[nbOfNodesSon-1];
10204 for(unsigned k=0;k<nbOfNodesSon;k++)
10206 m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
10207 m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
10214 std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
10218 std::map<int, std::set<int> >::const_iterator it=m.find(start);
10219 const std::set<int>& s=(*it).second;
10220 std::set<int> s2; s2.insert(prev);
10222 std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
10225 int val=*s3.begin();
10226 conn.push_back(start);
10233 conn.push_back(end);
10236 nodalRes->insertAtTheEnd(conn.begin(),conn.end());
10237 nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
10238 cellIds->pushBackSilent(i);
10244 * 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
10245 * 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
10246 * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
10247 * 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
10248 * 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.
10250 * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
10252 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
10254 std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
10257 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
10258 if(cm.getDimension()==2)
10260 const int *node=nodalConnBg+1;
10261 int startNode=*node++;
10262 double refX=coords[2*startNode];
10263 for(;node!=nodalConnEnd;node++)
10265 if(coords[2*(*node)]<refX)
10268 refX=coords[2*startNode];
10271 std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
10275 double angle0=-M_PI/2;
10280 double angleNext=0.;
10281 while(nextNode!=startNode)
10285 for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
10287 if(*node!=tmpOut.back() && *node!=prevNode)
10289 tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
10290 double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
10295 res=angle0-angleM+2.*M_PI;
10304 if(nextNode!=startNode)
10306 angle0=angleNext-M_PI;
10309 prevNode=tmpOut.back();
10310 tmpOut.push_back(nextNode);
10313 std::vector<int> tmp3(2*(sz-1));
10314 std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
10315 std::copy(nodalConnBg+1,nodalConnEnd,it);
10316 if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
10318 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10321 if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
10323 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10328 nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
10329 nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
10334 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10337 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10341 * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
10342 * 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.
10344 * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
10345 * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
10346 * \param [in,out] arr array in which the remove operation will be done.
10347 * \param [in,out] arrIndx array in the remove operation will modify
10348 * \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])
10349 * \return true if \b arr and \b arrIndx have been modified, false if not.
10351 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
10353 if(!arrIndx || !arr)
10354 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
10355 if(offsetForRemoval<0)
10356 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
10357 std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
10358 int nbOfGrps=arrIndx->getNumberOfTuples()-1;
10359 int *arrIPtr=arrIndx->getPointer();
10361 int previousArrI=0;
10362 const int *arrPtr=arr->getConstPointer();
10363 std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
10364 for(int i=0;i<nbOfGrps;i++,arrIPtr++)
10366 if(*arrIPtr-previousArrI>offsetForRemoval)
10368 for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
10370 if(s.find(*work)==s.end())
10371 arrOut.push_back(*work);
10374 previousArrI=*arrIPtr;
10375 *arrIPtr=(int)arrOut.size();
10377 if(arr->getNumberOfTuples()==(int)arrOut.size())
10379 arr->alloc((int)arrOut.size(),1);
10380 std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
10385 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10386 * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
10387 * The selection of extraction is done standardly in new2old format.
10388 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10390 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10391 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10392 * \param [in] arrIn arr origin array from which the extraction will be done.
10393 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10394 * \param [out] arrOut the resulting array
10395 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10396 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
10398 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10399 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10401 if(!arrIn || !arrIndxIn)
10402 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
10403 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10404 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10405 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
10406 std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
10407 const int *arrInPtr=arrIn->getConstPointer();
10408 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10409 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10411 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10412 int maxSizeOfArr=arrIn->getNumberOfTuples();
10413 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10414 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10415 arrIo->alloc((int)(sz+1),1);
10416 const int *idsIt=idsOfSelectBg;
10417 int *work=arrIo->getPointer();
10420 for(std::size_t i=0;i<sz;i++,work++,idsIt++)
10422 if(*idsIt>=0 && *idsIt<nbOfGrps)
10423 lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
10426 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10427 throw INTERP_KERNEL::Exception(oss.str().c_str());
10433 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
10434 oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
10435 throw INTERP_KERNEL::Exception(oss.str().c_str());
10438 arro->alloc(lgth,1);
10439 work=arro->getPointer();
10440 idsIt=idsOfSelectBg;
10441 for(std::size_t i=0;i<sz;i++,idsIt++)
10443 if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
10444 work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
10447 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
10448 oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10449 throw INTERP_KERNEL::Exception(oss.str().c_str());
10452 arrOut=arro.retn();
10453 arrIndexOut=arrIo.retn();
10457 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10458 * 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 ).
10459 * The selection of extraction is done standardly in new2old format.
10460 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10462 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10463 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10464 * \param [in] arrIn arr origin array from which the extraction will be done.
10465 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10466 * \param [out] arrOut the resulting array
10467 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10468 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
10470 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10471 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10473 if(!arrIn || !arrIndxIn)
10474 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
10475 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10476 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10477 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
10478 int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
10479 const int *arrInPtr=arrIn->getConstPointer();
10480 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10481 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10483 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10484 int maxSizeOfArr=arrIn->getNumberOfTuples();
10485 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10486 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10487 arrIo->alloc((int)(sz+1),1);
10488 int idsIt=idsOfSelectStart;
10489 int *work=arrIo->getPointer();
10492 for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
10494 if(idsIt>=0 && idsIt<nbOfGrps)
10495 lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
10498 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10499 throw INTERP_KERNEL::Exception(oss.str().c_str());
10505 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
10506 oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
10507 throw INTERP_KERNEL::Exception(oss.str().c_str());
10510 arro->alloc(lgth,1);
10511 work=arro->getPointer();
10512 idsIt=idsOfSelectStart;
10513 for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
10515 if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
10516 work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
10519 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
10520 oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10521 throw INTERP_KERNEL::Exception(oss.str().c_str());
10524 arrOut=arro.retn();
10525 arrIndexOut=arrIo.retn();
10529 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10530 * 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
10531 * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
10532 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
10534 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10535 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10536 * \param [in] arrIn arr origin array from which the extraction will be done.
10537 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10538 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
10539 * \param [in] srcArrIndex index array of \b srcArr
10540 * \param [out] arrOut the resulting array
10541 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10543 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
10545 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10546 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
10547 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10549 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10550 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
10551 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10552 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10553 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10554 std::vector<bool> v(nbOfTuples,true);
10556 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10557 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10558 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10560 if(*it>=0 && *it<nbOfTuples)
10563 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
10567 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
10568 throw INTERP_KERNEL::Exception(oss.str().c_str());
10571 srcArrIndexPtr=srcArrIndex->getConstPointer();
10572 arrIo->alloc(nbOfTuples+1,1);
10573 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
10574 const int *arrInPtr=arrIn->getConstPointer();
10575 const int *srcArrPtr=srcArr->getConstPointer();
10576 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
10577 int *arroPtr=arro->getPointer();
10578 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
10582 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
10583 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
10587 std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
10588 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
10589 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
10592 arrOut=arro.retn();
10593 arrIndexOut=arrIo.retn();
10597 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10598 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
10600 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10601 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10602 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
10603 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10604 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
10605 * \param [in] srcArrIndex index array of \b srcArr
10607 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
10609 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
10610 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
10612 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10613 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
10614 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10615 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10616 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10617 int *arrInOutPtr=arrInOut->getPointer();
10618 const int *srcArrPtr=srcArr->getConstPointer();
10619 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10621 if(*it>=0 && *it<nbOfTuples)
10623 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
10624 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
10627 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] !";
10628 throw INTERP_KERNEL::Exception(oss.str().c_str());
10633 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
10634 throw INTERP_KERNEL::Exception(oss.str().c_str());
10640 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
10641 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
10642 * 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]].
10643 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
10644 * A negative value in \b arrIn means that it is ignored.
10645 * 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.
10647 * \param [in] arrIn arr origin array from which the extraction will be done.
10648 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10649 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
10650 * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
10652 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
10654 int seed=0,nbOfDepthPeelingPerformed=0;
10655 return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
10659 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
10660 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
10661 * 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]].
10662 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
10663 * A negative value in \b arrIn means that it is ignored.
10664 * 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.
10665 * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
10666 * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
10667 * \param [in] arrIn arr origin array from which the extraction will be done.
10668 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10669 * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
10670 * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
10671 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
10672 * \sa MEDCouplingUMesh::partitionBySpreadZone
10674 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
10676 nbOfDepthPeelingPerformed=0;
10678 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
10679 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10682 DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
10686 std::vector<bool> fetched(nbOfTuples,false);
10687 return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
10690 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
10692 nbOfDepthPeelingPerformed=0;
10693 if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
10694 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
10695 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10696 std::vector<bool> fetched2(nbOfTuples,false);
10698 for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
10700 if(*seedElt>=0 && *seedElt<nbOfTuples)
10701 { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
10703 { 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()); }
10705 const int *arrInPtr=arrIn->getConstPointer();
10706 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10707 int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
10708 std::vector<int> idsToFetch1(seedBg,seedEnd);
10709 std::vector<int> idsToFetch2;
10710 std::vector<int> *idsToFetch=&idsToFetch1;
10711 std::vector<int> *idsToFetchOther=&idsToFetch2;
10712 while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
10714 for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
10715 for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
10717 { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
10718 std::swap(idsToFetch,idsToFetchOther);
10719 idsToFetchOther->clear();
10720 nbOfDepthPeelingPerformed++;
10722 int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
10724 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
10725 int *retPtr=ret->getPointer();
10726 for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
10733 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10734 * 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
10735 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
10736 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
10738 * \param [in] start begin of set of ids of the input extraction (included)
10739 * \param [in] end end of set of ids of the input extraction (excluded)
10740 * \param [in] step step of the set of ids in range mode.
10741 * \param [in] arrIn arr origin array from which the extraction will be done.
10742 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10743 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
10744 * \param [in] srcArrIndex index array of \b srcArr
10745 * \param [out] arrOut the resulting array
10746 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10748 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
10750 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10751 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
10752 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10754 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10755 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
10756 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10757 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10758 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10760 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10761 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10762 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
10764 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
10766 if(it>=0 && it<nbOfTuples)
10767 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
10770 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
10771 throw INTERP_KERNEL::Exception(oss.str().c_str());
10774 srcArrIndexPtr=srcArrIndex->getConstPointer();
10775 arrIo->alloc(nbOfTuples+1,1);
10776 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
10777 const int *arrInPtr=arrIn->getConstPointer();
10778 const int *srcArrPtr=srcArr->getConstPointer();
10779 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
10780 int *arroPtr=arro->getPointer();
10781 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
10783 int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
10786 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
10787 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
10791 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
10792 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
10795 arrOut=arro.retn();
10796 arrIndexOut=arrIo.retn();
10800 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10801 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
10803 * \param [in] start begin of set of ids of the input extraction (included)
10804 * \param [in] end end of set of ids of the input extraction (excluded)
10805 * \param [in] step step of the set of ids in range mode.
10806 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
10807 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10808 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
10809 * \param [in] srcArrIndex index array of \b srcArr
10811 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
10813 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
10814 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
10816 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10817 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
10818 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10819 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10820 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10821 int *arrInOutPtr=arrInOut->getPointer();
10822 const int *srcArrPtr=srcArr->getConstPointer();
10823 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
10825 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
10827 if(it>=0 && it<nbOfTuples)
10829 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
10830 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
10833 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
10834 throw INTERP_KERNEL::Exception(oss.str().c_str());
10839 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
10840 throw INTERP_KERNEL::Exception(oss.str().c_str());
10846 * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
10847 * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
10848 * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
10849 * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
10850 * The sum of measure field of returned mesh is equal to the sum of measure field of this.
10852 * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
10854 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
10856 checkFullyDefined();
10857 int mdim=getMeshDimension();
10858 int spaceDim=getSpaceDimension();
10860 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
10861 std::vector<DataArrayInt *> partition=partitionBySpreadZone();
10862 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
10863 std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
10864 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
10865 ret->setCoords(getCoords());
10866 ret->allocateCells((int)partition.size());
10868 for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
10870 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
10871 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
10875 cell=tmp->buildUnionOf2DMesh();
10878 cell=tmp->buildUnionOf3DMesh();
10881 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
10884 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
10887 ret->finishInsertingCells();
10892 * This method partitions \b this into contiguous zone.
10893 * This method only needs a well defined connectivity. Coordinates are not considered here.
10894 * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
10896 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
10898 int nbOfCellsCur=getNumberOfCells();
10899 std::vector<DataArrayInt *> ret;
10900 if(nbOfCellsCur<=0)
10902 DataArrayInt *neigh=0,*neighI=0;
10903 computeNeighborsOfCells(neigh,neighI);
10904 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
10905 std::vector<bool> fetchedCells(nbOfCellsCur,false);
10906 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
10908 while(seed<nbOfCellsCur)
10910 int nbOfPeelPerformed=0;
10911 ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
10912 seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
10914 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
10915 ret.push_back((*it).retn());
10920 * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
10921 * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
10923 * \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.
10924 * \return a newly allocated DataArrayInt to be managed by the caller.
10925 * \throw In case of \a code has not the right format (typically of size 3*n)
10927 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
10929 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
10930 std::size_t nb=code.size()/3;
10931 if(code.size()%3!=0)
10932 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
10933 ret->alloc((int)nb,2);
10934 int *retPtr=ret->getPointer();
10935 for(std::size_t i=0;i<nb;i++,retPtr+=2)
10937 retPtr[0]=code[3*i+2];
10938 retPtr[1]=code[3*i+2]+code[3*i+1];
10944 * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
10945 * All cells in \a this are expected to be linear 3D cells.
10946 * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
10947 * It leads to an increase to number of cells.
10948 * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
10949 * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints
10950 * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
10952 * \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.
10953 * For all other cells, the splitting policy will be ignored.
10954 * \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.
10955 * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
10956 * an id of old cell producing it. The caller is to delete this array using
10957 * decrRef() as it is no more needed.
10958 * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
10960 * \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
10961 * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
10963 * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
10964 * \throw If \a this is not fully constituted with linear 3D cells.
10965 * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
10967 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
10969 INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
10970 checkConnectivityFullyDefined();
10971 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10972 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
10973 int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
10974 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
10975 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
10976 int *retPt(ret->getPointer());
10977 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
10978 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
10979 const int *oldc(_nodal_connec->begin());
10980 const int *oldci(_nodal_connec_index->begin());
10981 const double *coords(_coords->begin());
10982 for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
10984 std::vector<int> a; std::vector<double> b;
10985 INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
10986 std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
10987 const int *aa(&a[0]);
10990 for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
10992 *it=(-(*(it))-1+nbNodes);
10993 addPts->insertAtTheEnd(b.begin(),b.end());
10994 nbNodes+=(int)b.size()/3;
10996 for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
10997 newConn->insertAtTheEnd(aa,aa+4);
10999 if(!addPts->empty())
11001 addPts->rearrange(3);
11002 nbOfAdditionalPoints=addPts->getNumberOfTuples();
11003 addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
11004 ret0->setCoords(addPts);
11008 nbOfAdditionalPoints=0;
11009 ret0->setCoords(getCoords());
11011 ret0->setNodalConnectivity(newConn);
11013 ret->computeOffsets2();
11014 n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
11015 return ret0.retn();
11019 * 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).
11021 * \sa MEDCouplingUMesh::split2DCells
11023 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
11025 checkConnectivityFullyDefined();
11026 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
11027 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11028 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11029 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11030 int prevPosOfCi(ciPtr[0]);
11031 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11033 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
11034 *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
11035 for(int j=0;j<sz;j++)
11037 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
11038 for(int k=0;k<sz2;k++)
11039 *cPtr++=subPtr[offset2+k];
11041 *cPtr++=oldConn[prevPosOfCi+j+2];
11044 prevPosOfCi=ciPtr[1];
11045 ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11048 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
11049 _nodal_connec->decrRef();
11050 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
11053 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11059 int ret(nodesCnter++);
11061 e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
11062 addCoo.insertAtTheEnd(newPt,newPt+2);
11069 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)
11072 int trueStart(start>=0?start:nbOfEdges+start);
11073 tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
11074 newConnOfCell->insertAtTheEnd(tmp,tmp+3);
11079 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11080 InternalAddPoint(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
11081 middles.push_back(tmp3+offset);
11084 middles.push_back(connBg[trueStart+nbOfEdges]);
11088 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)
11090 int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
11091 newConnOfCell->pushBackSilent(tmpEnd);
11096 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11097 InternalAddPoint(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11098 middles.push_back(tmp3+offset);
11101 middles.push_back(connBg[start+nbOfEdges]);
11105 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)
11111 int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
11112 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11113 InternalAddPoint(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11114 middles.push_back(tmp3+offset);
11117 middles.push_back(connBg[start+nbOfEdges]);
11124 * 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 ) .
11125 * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
11127 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
11129 std::size_t sz(std::distance(connBg,connEnd));
11130 if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
11131 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
11133 INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
11134 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
11135 unsigned nbs(cm.getNumberOfSons2(connBg+1,sz)),nbOfHit(0);
11136 int posBaseElt(0),posEndElt(0),nbOfTurn(0);
11137 INTERP_KERNEL::NormalizedCellType typeOfSon;
11138 std::vector<int> middles;
11140 for(;nbOfHit<nbs;nbOfTurn++)
11142 cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
11143 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
11144 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11147 unsigned endI(nbs-nbOfHit);
11148 for(unsigned i=0;i<endI;i++)
11150 cm.fillSonCellNodalConnectivity2(posBaseElt+(int)i+1,connBg+1,sz,tmpConn,typeOfSon);
11151 INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11152 INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11153 bool isColinear(eint->areColinears());
11165 {//look if the first edge of cell is not colinear with last edges in this case the start of nodal connectivity is shifted back
11166 unsigned endII(nbs-nbOfHit-1);//warning nbOfHit can be modified, so put end condition in a variable.
11167 for(unsigned ii=0;ii<endII;ii++)
11169 cm.fillSonCellNodalConnectivity2(nbs-ii-1,connBg+1,sz,tmpConn,typeOfSon);
11170 eCand=MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m);
11171 eint=INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand);
11172 isColinear=eint->areColinears();
11188 //push [posBaseElt,posEndElt) in newConnOfCell using e
11190 EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11191 else if(nbOfHit!=nbs)
11192 EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11194 EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11195 posBaseElt=posEndElt;
11198 if(!middles.empty())
11199 newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
11204 * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
11206 * \return int - the number of new nodes created.
11207 * \sa MEDCouplingUMesh::split2DCells
11209 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
11212 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
11213 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11214 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
11215 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11216 const int *midPtr(mid->begin()),*midIPtr(midI->begin());
11217 const double *oldCoordsPtr(getCoords()->begin());
11218 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11219 int prevPosOfCi(ciPtr[0]);
11220 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11222 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
11223 for(int j=0;j<sz;j++)
11224 { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
11225 *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
11226 for(int j=0;j<sz;j++)//loop over subedges of oldConn
11228 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
11232 cPtr[1]=oldConn[prevPosOfCi+2+j];
11233 cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
11236 std::vector<INTERP_KERNEL::Node *> ns(3);
11237 ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
11238 ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
11239 ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
11240 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
11241 for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
11243 cPtr[1]=subPtr[offset2+k];
11244 cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
11246 int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
11248 { cPtr[1]=tmpEnd; }
11249 cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
11251 prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
11252 ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11255 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
11256 _nodal_connec->decrRef();
11257 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
11258 addCoo->rearrange(2);
11259 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
11261 return addCoo->getNumberOfTuples();
11264 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
11265 _own_cell(true),_cell_id(-1),_nb_cell(0)
11270 _nb_cell=mesh->getNumberOfCells();
11274 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
11282 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
11283 _own_cell(false),_cell_id(bg-1),
11290 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
11293 if(_cell_id<_nb_cell)
11302 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
11308 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
11310 return new MEDCouplingUMeshCellByTypeIterator(_mesh);
11313 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
11319 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
11327 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
11333 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
11338 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
11343 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
11345 return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
11348 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
11353 _nb_cell=mesh->getNumberOfCells();
11357 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
11364 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
11366 const int *c=_mesh->getNodalConnectivity()->getConstPointer();
11367 const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
11368 if(_cell_id<_nb_cell)
11370 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
11371 int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
11372 int startId=_cell_id;
11373 _cell_id+=nbOfElems;
11374 return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
11380 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
11384 _conn=mesh->getNodalConnectivity()->getPointer();
11385 _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
11389 void MEDCouplingUMeshCell::next()
11391 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11396 _conn_lgth=_conn_indx[1]-_conn_indx[0];
11399 std::string MEDCouplingUMeshCell::repr() const
11401 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11403 std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
11405 std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
11409 return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
11412 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
11414 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11415 return (INTERP_KERNEL::NormalizedCellType)_conn[0];
11417 return INTERP_KERNEL::NORM_ERROR;
11420 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
11423 if(_conn_lgth!=NOTICABLE_FIRST_VAL)