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::getDirectChildren() const
127 std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildren());
129 ret.push_back(_nodal_connec);
130 if(_nodal_connec_index)
131 ret.push_back(_nodal_connec_index);
135 void MEDCouplingUMesh::updateTime() const
137 MEDCouplingPointSet::updateTime();
140 updateTimeWith(*_nodal_connec);
142 if(_nodal_connec_index)
144 updateTimeWith(*_nodal_connec_index);
148 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
153 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
154 * then \a this mesh is most probably is writable, exchangeable and available for most
155 * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
156 * this method to check that all is in order with \a this mesh.
157 * \throw If the mesh dimension is not set.
158 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
159 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
160 * \throw If the connectivity data array has more than one component.
161 * \throw If the connectivity data array has a named component.
162 * \throw If the connectivity index data array has more than one component.
163 * \throw If the connectivity index data array has a named component.
165 void MEDCouplingUMesh::checkCoherency() const
168 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
170 MEDCouplingPointSet::checkCoherency();
171 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
173 if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
175 std::ostringstream message;
176 message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
177 throw INTERP_KERNEL::Exception(message.str().c_str());
182 if(_nodal_connec->getNumberOfComponents()!=1)
183 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
184 if(_nodal_connec->getInfoOnComponent(0)!="")
185 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
189 throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
190 if(_nodal_connec_index)
192 if(_nodal_connec_index->getNumberOfComponents()!=1)
193 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
194 if(_nodal_connec_index->getInfoOnComponent(0)!="")
195 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
199 throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
203 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
204 * then \a this mesh is most probably is writable, exchangeable and available for all
205 * algorithms. <br> In addition to the checks performed by checkCoherency(), this
206 * method thoroughly checks the nodal connectivity.
207 * \param [in] eps - a not used parameter.
208 * \throw If the mesh dimension is not set.
209 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
210 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
211 * \throw If the connectivity data array has more than one component.
212 * \throw If the connectivity data array has a named component.
213 * \throw If the connectivity index data array has more than one component.
214 * \throw If the connectivity index data array has a named component.
215 * \throw If number of nodes defining an element does not correspond to the type of element.
216 * \throw If the nodal connectivity includes an invalid node id.
218 void MEDCouplingUMesh::checkCoherency1(double eps) const
223 int meshDim=getMeshDimension();
224 int nbOfNodes=getNumberOfNodes();
225 int nbOfCells=getNumberOfCells();
226 const int *ptr=_nodal_connec->getConstPointer();
227 const int *ptrI=_nodal_connec_index->getConstPointer();
228 for(int i=0;i<nbOfCells;i++)
230 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
231 if((int)cm.getDimension()!=meshDim)
233 std::ostringstream oss;
234 oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
235 throw INTERP_KERNEL::Exception(oss.str().c_str());
237 int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
239 if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
241 std::ostringstream oss;
242 oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " << cm.getNumberOfNodes();
243 oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
244 throw INTERP_KERNEL::Exception(oss.str().c_str());
246 for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
251 if(nodeId>=nbOfNodes)
253 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes !";
254 throw INTERP_KERNEL::Exception(oss.str().c_str());
259 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " in connectivity ! sounds bad !";
260 throw INTERP_KERNEL::Exception(oss.str().c_str());
264 if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
266 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #-1 in connectivity ! sounds bad !";
267 throw INTERP_KERNEL::Exception(oss.str().c_str());
276 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
277 * then \a this mesh is most probably is writable, exchangeable and available for all
278 * algorithms. <br> This method performs the same checks as checkCoherency1() does.
279 * \param [in] eps - a not used parameter.
280 * \throw If the mesh dimension is not set.
281 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
282 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
283 * \throw If the connectivity data array has more than one component.
284 * \throw If the connectivity data array has a named component.
285 * \throw If the connectivity index data array has more than one component.
286 * \throw If the connectivity index data array has a named component.
287 * \throw If number of nodes defining an element does not correspond to the type of element.
288 * \throw If the nodal connectivity includes an invalid node id.
290 void MEDCouplingUMesh::checkCoherency2(double eps) const
292 checkCoherency1(eps);
296 * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
297 * elements contained in the mesh. For more info on the mesh dimension see
298 * \ref MEDCouplingUMeshPage.
299 * \param [in] meshDim - a new mesh dimension.
300 * \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
302 void MEDCouplingUMesh::setMeshDimension(int meshDim)
304 if(meshDim<-1 || meshDim>3)
305 throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
311 * Allocates memory to store an estimation of the given number of cells. Closer is the estimation to the number of cells effectively inserted,
312 * less will be the needs to realloc. If the number of cells to be inserted is not known simply put 0 to this parameter.
313 * If a nodal connectivity previouly existed before the call of this method, it will be reset.
315 * \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
317 * \if ENABLE_EXAMPLES
318 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
319 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
322 void MEDCouplingUMesh::allocateCells(int nbOfCells)
325 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
326 if(_nodal_connec_index)
328 _nodal_connec_index->decrRef();
332 _nodal_connec->decrRef();
334 _nodal_connec_index=DataArrayInt::New();
335 _nodal_connec_index->reserve(nbOfCells+1);
336 _nodal_connec_index->pushBackSilent(0);
337 _nodal_connec=DataArrayInt::New();
338 _nodal_connec->reserve(2*nbOfCells);
344 * Appends a cell to the connectivity array. For deeper understanding what is
345 * happening see \ref MEDCouplingUMeshNodalConnectivity.
346 * \param [in] type - type of cell to add.
347 * \param [in] size - number of nodes constituting this cell.
348 * \param [in] nodalConnOfCell - the connectivity of the cell to add.
350 * \if ENABLE_EXAMPLES
351 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
352 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
355 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
357 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
358 if(_nodal_connec_index==0)
359 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
360 if((int)cm.getDimension()==_mesh_dim)
363 if(size!=(int)cm.getNumberOfNodes())
365 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
366 oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
367 throw INTERP_KERNEL::Exception(oss.str().c_str());
369 int idx=_nodal_connec_index->back();
371 _nodal_connec_index->pushBackSilent(val);
372 _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
377 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
378 oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
379 oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
380 throw INTERP_KERNEL::Exception(oss.str().c_str());
385 * Compacts data arrays to release unused memory. This method is to be called after
386 * finishing cell insertion using \a this->insertNextCell().
388 * \if ENABLE_EXAMPLES
389 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
390 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
393 void MEDCouplingUMesh::finishInsertingCells()
395 _nodal_connec->pack();
396 _nodal_connec_index->pack();
397 _nodal_connec->declareAsNew();
398 _nodal_connec_index->declareAsNew();
403 * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
404 * Useful for python users.
406 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
408 return new MEDCouplingUMeshCellIterator(this);
412 * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
413 * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
414 * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
415 * Useful for python users.
417 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
419 if(!checkConsecutiveCellTypes())
420 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
421 return new MEDCouplingUMeshCellByTypeEntry(this);
425 * Returns a set of all cell types available in \a this mesh.
426 * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
427 * \warning this method does not throw any exception even if \a this is not defined.
428 * \sa MEDCouplingUMesh::getAllGeoTypesSorted
430 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
436 * This method returns the sorted list of geometric types in \a this.
437 * 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
438 * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
440 * \throw if connectivity in \a this is not correctly defined.
442 * \sa MEDCouplingMesh::getAllGeoTypes
444 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
446 std::vector<INTERP_KERNEL::NormalizedCellType> ret;
447 checkConnectivityFullyDefined();
448 int nbOfCells(getNumberOfCells());
451 if(getMeshLength()<1)
452 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
453 const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
454 ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
455 for(int i=1;i<nbOfCells;i++,ci++)
456 if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
457 ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
462 * This method is a method that compares \a this and \a other.
463 * This method compares \b all attributes, even names and component names.
465 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
468 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
469 std::ostringstream oss; oss.precision(15);
470 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
473 reason="mesh given in input is not castable in MEDCouplingUMesh !";
476 if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
478 if(_mesh_dim!=otherC->_mesh_dim)
480 oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" << otherC->_mesh_dim;
484 if(_types!=otherC->_types)
486 oss << "umesh geometric type mismatch :\nThis geometric types are :";
487 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
488 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
489 oss << "\nOther geometric types are :";
490 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
491 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
495 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
496 if(_nodal_connec==0 || otherC->_nodal_connec==0)
498 reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
501 if(_nodal_connec!=otherC->_nodal_connec)
502 if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
504 reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
507 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
508 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
510 reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
513 if(_nodal_connec_index!=otherC->_nodal_connec_index)
514 if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
516 reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
523 * Checks if data arrays of this mesh (node coordinates, nodal
524 * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
526 * \param [in] other - the mesh to compare with.
527 * \param [in] prec - precision value used to compare node coordinates.
528 * \return bool - \a true if the two meshes are same.
530 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
532 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
535 if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
537 if(_mesh_dim!=otherC->_mesh_dim)
539 if(_types!=otherC->_types)
541 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
542 if(_nodal_connec==0 || otherC->_nodal_connec==0)
544 if(_nodal_connec!=otherC->_nodal_connec)
545 if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
547 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
548 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
550 if(_nodal_connec_index!=otherC->_nodal_connec_index)
551 if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
557 * Checks if \a this and \a other meshes are geometrically equivalent with high
558 * probability, else an exception is thrown. The meshes are considered equivalent if
559 * (1) meshes contain the same number of nodes and the same number of elements of the
560 * same types (2) three cells of the two meshes (first, last and middle) are based
561 * on coincident nodes (with a specified precision).
562 * \param [in] other - the mesh to compare with.
563 * \param [in] prec - the precision used to compare nodes of the two meshes.
564 * \throw If the two meshes do not match.
566 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
568 MEDCouplingPointSet::checkFastEquivalWith(other,prec);
569 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
571 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !");
575 * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
576 * cells each node belongs to.
577 * \warning For speed reasons, this method does not check if node ids in the nodal
578 * connectivity correspond to the size of node coordinates array.
579 * \param [in,out] revNodal - an array holding ids of cells sharing each node.
580 * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
581 * dividing cell ids in \a revNodal into groups each referring to one
582 * node. Its every element (except the last one) is an index pointing to the
583 * first id of a group of cells. For example cells sharing the node #1 are
584 * described by following range of indices:
585 * [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
586 * \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
587 * Number of cells sharing the *i*-th node is
588 * \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
589 * \throw If the coordinates array is not set.
590 * \throw If the nodal connectivity of cells is not defined.
592 * \if ENABLE_EXAMPLES
593 * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
594 * \ref py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
597 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
600 int nbOfNodes=getNumberOfNodes();
601 int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
602 revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
603 std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
604 const int *conn=_nodal_connec->getConstPointer();
605 const int *connIndex=_nodal_connec_index->getConstPointer();
606 int nbOfCells=getNumberOfCells();
607 int nbOfEltsInRevNodal=0;
608 for(int eltId=0;eltId<nbOfCells;eltId++)
610 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
611 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
612 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
613 if(*iter>=0)//for polyhedrons
615 nbOfEltsInRevNodal++;
616 revNodalIndxPtr[(*iter)+1]++;
619 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
620 int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
621 revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
622 std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
623 for(int eltId=0;eltId<nbOfCells;eltId++)
625 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
626 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
627 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
628 if(*iter>=0)//for polyhedrons
629 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
635 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
640 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
646 if(cm.getOrientationStatus(nb,conn1,conn2))
653 class MinusOneSonsGenerator
656 MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
657 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
658 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
659 static const int DELTA=1;
661 const INTERP_KERNEL::CellModel& _cm;
664 class MinusOneSonsGeneratorBiQuadratic
667 MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
668 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
669 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
670 static const int DELTA=1;
672 const INTERP_KERNEL::CellModel& _cm;
675 class MinusTwoSonsGenerator
678 MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
679 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
680 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
681 static const int DELTA=2;
683 const INTERP_KERNEL::CellModel& _cm;
689 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
690 * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
691 * describing correspondence between cells of \a this and the result meshes are
692 * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
693 * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
694 * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
695 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
696 * \warning For speed reasons, this method does not check if node ids in the nodal
697 * connectivity correspond to the size of node coordinates array.
698 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
699 * to write this mesh to the MED file, its cells must be sorted using
700 * sortCellsInMEDFileFrmt().
701 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
702 * each cell of \a this mesh.
703 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
704 * dividing cell ids in \a desc into groups each referring to one
705 * cell of \a this mesh. Its every element (except the last one) is an index
706 * pointing to the first id of a group of cells. For example cells of the
707 * result mesh bounding the cell #1 of \a this mesh are described by following
709 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
710 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
711 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
712 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
713 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
714 * by each cell of the result mesh.
715 * \param [in,out] revDescIndx - the array, of length one more than number of cells
716 * in the result mesh,
717 * dividing cell ids in \a revDesc into groups each referring to one
718 * cell of the result mesh the same way as \a descIndx divides \a desc.
719 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
720 * delete this mesh using decrRef() as it is no more needed.
721 * \throw If the coordinates array is not set.
722 * \throw If the nodal connectivity of cells is node defined.
723 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
724 * revDescIndx == NULL.
726 * \if ENABLE_EXAMPLES
727 * \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
728 * \ref py_mcumesh_buildDescendingConnectivity "Here is a Python example".
730 * \sa buildDescendingConnectivity2()
732 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
734 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
738 * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
739 * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
740 * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
741 * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
742 * \sa MEDCouplingUMesh::buildDescendingConnectivity
744 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
747 if(getMeshDimension()!=3)
748 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
749 return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
753 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
754 * this->getMeshDimension(), that bound cells of \a this mesh. In
755 * addition arrays describing correspondence between cells of \a this and the result
756 * meshes are returned. The arrays \a desc and \a descIndx describe the descending
757 * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
758 * mesh. This method differs from buildDescendingConnectivity() in that apart
759 * from cell ids, \a desc returns mutual orientation of cells in \a this and the
760 * result meshes. So a positive id means that order of nodes in corresponding cells
761 * of two meshes is same, and a negative id means a reverse order of nodes. Since a
762 * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
763 * i.e. cell ids are one-based.
764 * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
765 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
766 * \warning For speed reasons, this method does not check if node ids in the nodal
767 * connectivity correspond to the size of node coordinates array.
768 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
769 * to write this mesh to the MED file, its cells must be sorted using
770 * sortCellsInMEDFileFrmt().
771 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
772 * each cell of \a this mesh.
773 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
774 * dividing cell ids in \a desc into groups each referring to one
775 * cell of \a this mesh. Its every element (except the last one) is an index
776 * pointing to the first id of a group of cells. For example cells of the
777 * result mesh bounding the cell #1 of \a this mesh are described by following
779 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
780 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
781 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
782 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
783 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
784 * by each cell of the result mesh.
785 * \param [in,out] revDescIndx - the array, of length one more than number of cells
786 * in the result mesh,
787 * dividing cell ids in \a revDesc into groups each referring to one
788 * cell of the result mesh the same way as \a descIndx divides \a desc.
789 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
790 * shares the node coordinates array with \a this mesh. The caller is to
791 * delete this mesh using decrRef() as it is no more needed.
792 * \throw If the coordinates array is not set.
793 * \throw If the nodal connectivity of cells is node defined.
794 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
795 * revDescIndx == NULL.
797 * \if ENABLE_EXAMPLES
798 * \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
799 * \ref py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
801 * \sa buildDescendingConnectivity()
803 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
805 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
809 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
810 * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
811 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
812 * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
814 * \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
815 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
816 * \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.
818 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
820 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
821 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
822 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
823 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
824 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
826 ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
830 * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
831 * 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,
832 * excluding a set of meshdim-1 cells in input descending connectivity.
833 * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
834 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
835 * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
837 * \param [in] desc descending connectivity array.
838 * \param [in] descIndx descending connectivity index array used to walk through \b desc.
839 * \param [in] revDesc reverse descending connectivity array.
840 * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
841 * \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
842 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
843 * \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.
845 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
846 DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx)
848 if(!desc || !descIndx || !revDesc || !revDescIndx)
849 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
850 const int *descPtr=desc->getConstPointer();
851 const int *descIPtr=descIndx->getConstPointer();
852 const int *revDescPtr=revDesc->getConstPointer();
853 const int *revDescIPtr=revDescIndx->getConstPointer();
855 int nbCells=descIndx->getNumberOfTuples()-1;
856 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
857 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
858 int *out1Ptr=out1->getPointer();
860 out0->reserve(desc->getNumberOfTuples());
861 for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
863 for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
865 std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
867 out0->insertAtTheEnd(s.begin(),s.end());
869 *out1Ptr=out0->getNumberOfTuples();
871 neighbors=out0.retn();
872 neighborsIndx=out1.retn();
876 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
877 * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
878 * This method lists node by node in \b this which are its neighbors. To compute the result only connectivities are considered.
879 * The neighbor nodes of node having id 'nodeId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
881 * \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
882 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
883 * \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.
885 void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayInt *&neighbors, DataArrayInt *&neighborsIdx) const
888 int mdim(getMeshDimension()),nbNodes(getNumberOfNodes());
889 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descIndx(DataArrayInt::New()),revDesc(DataArrayInt::New()),revDescIndx(DataArrayInt::New());
890 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh1D;
895 mesh1D=explode3DMeshTo1D(desc,descIndx,revDesc,revDescIndx);
900 mesh1D=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
905 mesh1D=const_cast<MEDCouplingUMesh *>(this);
911 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2,1] !");
914 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=0; revDescIndx=0;
915 mesh1D->getReverseNodalConnectivity(desc,descIndx);
916 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0(DataArrayInt::New());
917 ret0->alloc(desc->getNumberOfTuples(),1);
918 int *r0Pt(ret0->getPointer());
919 const int *c1DPtr(mesh1D->getNodalConnectivity()->begin()),*rn(desc->begin()),*rni(descIndx->begin());
920 for(int i=0;i<nbNodes;i++,rni++)
922 for(const int *oneDCellIt=rn+rni[0];oneDCellIt!=rn+rni[1];oneDCellIt++)
923 *r0Pt++=c1DPtr[3*(*oneDCellIt)+1]==i?c1DPtr[3*(*oneDCellIt)+2]:c1DPtr[3*(*oneDCellIt)+1];
925 neighbors=ret0.retn();
926 neighborsIdx=descIndx.retn();
932 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
933 * For speed reasons no check of this will be done.
935 template<class SonsGenerator>
936 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
938 if(!desc || !descIndx || !revDesc || !revDescIndx)
939 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
940 checkConnectivityFullyDefined();
941 int nbOfCells=getNumberOfCells();
942 int nbOfNodes=getNumberOfNodes();
943 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
944 int *revNodalIndxPtr=revNodalIndx->getPointer();
945 const int *conn=_nodal_connec->getConstPointer();
946 const int *connIndex=_nodal_connec_index->getConstPointer();
947 std::string name="Mesh constituent of "; name+=getName();
948 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA);
949 ret->setCoords(getCoords());
950 ret->allocateCells(2*nbOfCells);
951 descIndx->alloc(nbOfCells+1,1);
952 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
953 int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
954 for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
956 int pos=connIndex[eltId];
957 int posP1=connIndex[eltId+1];
958 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
959 SonsGenerator sg(cm);
960 unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
961 INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
962 for(unsigned i=0;i<nbOfSons;i++)
964 INTERP_KERNEL::NormalizedCellType cmsId;
965 unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
966 for(unsigned k=0;k<nbOfNodesSon;k++)
968 revNodalIndxPtr[tmp[k]+1]++;
969 ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
970 revDesc2->pushBackSilent(eltId);
972 descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
974 int nbOfCellsM1=ret->getNumberOfCells();
975 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
976 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
977 std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
978 int *revNodalPtr=revNodal->getPointer();
979 const int *connM1=ret->getNodalConnectivity()->getConstPointer();
980 const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
981 for(int eltId=0;eltId<nbOfCellsM1;eltId++)
983 const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
984 const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
985 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
986 if(*iter>=0)//for polyhedrons
987 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
990 DataArrayInt *commonCells=0,*commonCellsI=0;
991 FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
992 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
993 const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
994 int newNbOfCellsM1=-1;
995 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
996 commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
997 std::vector<bool> isImpacted(nbOfCellsM1,false);
998 for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
999 for(int work2=work[0];work2!=work[1];work2++)
1000 isImpacted[commonCellsPtr[work2]]=true;
1001 const int *o2nM1Ptr=o2nM1->getConstPointer();
1002 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
1003 const int *n2oM1Ptr=n2oM1->getConstPointer();
1004 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
1005 ret2->copyTinyInfoFrom(this);
1006 desc->alloc(descIndx->back(),1);
1007 int *descPtr=desc->getPointer();
1008 const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
1009 for(int i=0;i<nbOfCellsM1;i++,descPtr++)
1012 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1015 if(i!=n2oM1Ptr[o2nM1Ptr[i]])
1017 const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
1018 *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
1021 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1024 revDesc->reserve(newNbOfCellsM1);
1025 revDescIndx->alloc(newNbOfCellsM1+1,1);
1026 int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
1027 const int *revDesc2Ptr=revDesc2->getConstPointer();
1028 for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
1030 int oldCellIdM1=n2oM1Ptr[i];
1031 if(!isImpacted[oldCellIdM1])
1033 revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
1034 revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
1038 for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
1039 revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
1040 revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
1048 struct MEDCouplingAccVisit
1050 MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1051 int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1052 int _new_nb_of_nodes;
1058 * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1059 * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1060 * array of cell ids. Pay attention that after conversion all algorithms work slower
1061 * with \a this mesh than before conversion. <br> If an exception is thrown during the
1062 * conversion due presence of invalid ids in the array of cells to convert, as a
1063 * result \a this mesh contains some already converted elements. In this case the 2D
1064 * mesh remains valid but 3D mesh becomes \b inconsistent!
1065 * \warning This method can significantly modify the order of geometric types in \a this,
1066 * hence, to write this mesh to the MED file, its cells must be sorted using
1067 * sortCellsInMEDFileFrmt().
1068 * \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1069 * \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1070 * cellIdsToConvertBg.
1071 * \throw If the coordinates array is not set.
1072 * \throw If the nodal connectivity of cells is node defined.
1073 * \throw If dimension of \a this mesh is not either 2 or 3.
1075 * \if ENABLE_EXAMPLES
1076 * \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1077 * \ref py_mcumesh_convertToPolyTypes "Here is a Python example".
1080 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1082 checkFullyDefined();
1083 int dim=getMeshDimension();
1085 throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1086 int nbOfCells(getNumberOfCells());
1089 const int *connIndex=_nodal_connec_index->getConstPointer();
1090 int *conn=_nodal_connec->getPointer();
1091 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1093 if(*iter>=0 && *iter<nbOfCells)
1095 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1096 if(!cm.isQuadratic())
1097 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1099 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1103 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1104 oss << " in range [0," << nbOfCells << ") !";
1105 throw INTERP_KERNEL::Exception(oss.str().c_str());
1111 int *connIndex(_nodal_connec_index->getPointer());
1112 const int *connOld(_nodal_connec->getConstPointer());
1113 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1114 std::vector<bool> toBeDone(nbOfCells,false);
1115 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1117 if(*iter>=0 && *iter<nbOfCells)
1118 toBeDone[*iter]=true;
1121 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1122 oss << " in range [0," << nbOfCells << ") !";
1123 throw INTERP_KERNEL::Exception(oss.str().c_str());
1126 for(int cellId=0;cellId<nbOfCells;cellId++)
1128 int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1129 int lgthOld(posP1-pos-1);
1130 if(toBeDone[cellId])
1132 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1133 unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1134 int *tmp(new int[nbOfFaces*lgthOld+1]);
1135 int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1136 for(unsigned j=0;j<nbOfFaces;j++)
1138 INTERP_KERNEL::NormalizedCellType type;
1139 unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1143 std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1144 connNew->pushBackValsSilent(tmp,tmp+newLgth);
1145 connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1150 connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1151 connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1154 setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1160 * Converts all cells to either polygons (if \a this is a 2D mesh) or
1161 * polyhedrons (if \a this is a 3D mesh).
1162 * \warning As this method is purely for user-friendliness and no optimization is
1163 * done to avoid construction of a useless vector, this method can be costly
1165 * \throw If the coordinates array is not set.
1166 * \throw If the nodal connectivity of cells is node defined.
1167 * \throw If dimension of \a this mesh is not either 2 or 3.
1169 void MEDCouplingUMesh::convertAllToPoly()
1171 int nbOfCells=getNumberOfCells();
1172 std::vector<int> cellIds(nbOfCells);
1173 for(int i=0;i<nbOfCells;i++)
1175 convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1179 * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1180 * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1181 * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1182 * base facet of the volume and the second half of nodes describes an opposite facet
1183 * having the same number of nodes as the base one. This method converts such
1184 * connectivity to a valid polyhedral format where connectivity of each facet is
1185 * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1186 * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1187 * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1188 * a correct orientation of the first facet of a polyhedron, else orientation of a
1189 * corrected cell is reverse.<br>
1190 * This method is useful to build an extruded unstructured mesh with polyhedrons as
1191 * it releases the user from boring description of polyhedra connectivity in the valid
1193 * \throw If \a this->getMeshDimension() != 3.
1194 * \throw If \a this->getSpaceDimension() != 3.
1195 * \throw If the nodal connectivity of cells is not defined.
1196 * \throw If the coordinates array is not set.
1197 * \throw If \a this mesh contains polyhedrons with the valid connectivity.
1198 * \throw If \a this mesh contains polyhedrons with odd number of nodes.
1200 * \if ENABLE_EXAMPLES
1201 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1202 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1205 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1207 checkFullyDefined();
1208 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1209 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1210 int nbOfCells=getNumberOfCells();
1211 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1212 newCi->alloc(nbOfCells+1,1);
1213 int *newci=newCi->getPointer();
1214 const int *ci=_nodal_connec_index->getConstPointer();
1215 const int *c=_nodal_connec->getConstPointer();
1217 for(int i=0;i<nbOfCells;i++)
1219 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1220 if(type==INTERP_KERNEL::NORM_POLYHED)
1222 if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1224 std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1225 throw INTERP_KERNEL::Exception(oss.str().c_str());
1227 std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1230 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 !";
1231 throw INTERP_KERNEL::Exception(oss.str().c_str());
1234 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)
1237 newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1239 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1240 newC->alloc(newci[nbOfCells],1);
1241 int *newc=newC->getPointer();
1242 for(int i=0;i<nbOfCells;i++)
1244 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1245 if(type==INTERP_KERNEL::NORM_POLYHED)
1247 std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1248 newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1250 for(std::size_t j=0;j<n1;j++)
1252 newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1254 newc[n1+5*j+1]=c[ci[i]+1+j];
1255 newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1256 newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1257 newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1262 newc=std::copy(c+ci[i],c+ci[i+1],newc);
1264 _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1265 _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1270 * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1271 * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1272 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1273 * to write this mesh to the MED file, its cells must be sorted using
1274 * sortCellsInMEDFileFrmt().
1275 * \return \c true if at least one cell has been converted, \c false else. In the
1276 * last case the nodal connectivity remains unchanged.
1277 * \throw If the coordinates array is not set.
1278 * \throw If the nodal connectivity of cells is not defined.
1279 * \throw If \a this->getMeshDimension() < 0.
1281 bool MEDCouplingUMesh::unPolyze()
1283 checkFullyDefined();
1284 int mdim=getMeshDimension();
1286 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1289 int nbOfCells=getNumberOfCells();
1292 int initMeshLgth=getMeshLength();
1293 int *conn=_nodal_connec->getPointer();
1294 int *index=_nodal_connec_index->getPointer();
1299 for(int i=0;i<nbOfCells;i++)
1301 lgthOfCurCell=index[i+1]-posOfCurCell;
1302 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1303 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1304 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1308 switch(cm.getDimension())
1312 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1313 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1314 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1319 int nbOfFaces,lgthOfPolyhConn;
1320 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1321 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1326 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1330 ret=ret || (newType!=type);
1331 conn[newPos]=newType;
1333 posOfCurCell=index[i+1];
1338 std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1339 newPos+=lgthOfCurCell;
1340 posOfCurCell+=lgthOfCurCell;
1344 if(newPos!=initMeshLgth)
1345 _nodal_connec->reAlloc(newPos);
1352 * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1353 * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1354 * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells.
1356 * \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
1359 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1361 checkFullyDefined();
1362 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1363 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1364 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1365 coords->recenterForMaxPrecision(eps);
1367 int nbOfCells=getNumberOfCells();
1368 const int *conn=_nodal_connec->getConstPointer();
1369 const int *index=_nodal_connec_index->getConstPointer();
1370 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1371 connINew->alloc(nbOfCells+1,1);
1372 int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1373 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1375 for(int i=0;i<nbOfCells;i++,connINewPtr++)
1377 if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1379 SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1383 connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1384 *connINewPtr=connNew->getNumberOfTuples();
1387 setConnectivity(connNew,connINew,false);
1391 * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1392 * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1393 * the format of returned DataArrayInt instance.
1395 * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1396 * \sa MEDCouplingUMesh::getNodeIdsInUse
1398 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1400 checkConnectivityFullyDefined();
1401 int nbOfCells=getNumberOfCells();
1402 const int *connIndex=_nodal_connec_index->getConstPointer();
1403 const int *conn=_nodal_connec->getConstPointer();
1404 const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1405 int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1406 std::vector<bool> retS(maxElt,false);
1407 for(int i=0;i<nbOfCells;i++)
1408 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1412 for(int i=0;i<maxElt;i++)
1415 DataArrayInt *ret=DataArrayInt::New();
1417 int *retPtr=ret->getPointer();
1418 for(int i=0;i<maxElt;i++)
1425 * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1426 * \sa MEDCouplingUMesh::getNodeIdsInUse
1428 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1430 int nbOfNodes=(int)nodeIdsInUse.size();
1431 int nbOfCells=getNumberOfCells();
1432 const int *connIndex=_nodal_connec_index->getConstPointer();
1433 const int *conn=_nodal_connec->getConstPointer();
1434 for(int i=0;i<nbOfCells;i++)
1435 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1438 if(conn[j]<nbOfNodes)
1439 nodeIdsInUse[conn[j]]=true;
1442 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1443 throw INTERP_KERNEL::Exception(oss.str().c_str());
1449 * Finds nodes not used in any cell and returns an array giving a new id to every node
1450 * by excluding the unused nodes, for which the array holds -1. The result array is
1451 * a mapping in "Old to New" mode.
1452 * \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1453 * \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1454 * this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1455 * if the node is unused or a new id else. The caller is to delete this
1456 * array using decrRef() as it is no more needed.
1457 * \throw If the coordinates array is not set.
1458 * \throw If the nodal connectivity of cells is not defined.
1459 * \throw If the nodal connectivity includes an invalid id.
1461 * \if ENABLE_EXAMPLES
1462 * \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1463 * \ref py_mcumesh_getNodeIdsInUse "Here is a Python example".
1465 * \sa computeNodeIdsAlg()
1467 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1470 int nbOfNodes=getNumberOfNodes();
1471 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1472 ret->alloc(nbOfNodes,1);
1473 int *traducer=ret->getPointer();
1474 std::fill(traducer,traducer+nbOfNodes,-1);
1475 int nbOfCells=getNumberOfCells();
1476 const int *connIndex=_nodal_connec_index->getConstPointer();
1477 const int *conn=_nodal_connec->getConstPointer();
1478 for(int i=0;i<nbOfCells;i++)
1479 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1482 if(conn[j]<nbOfNodes)
1483 traducer[conn[j]]=1;
1486 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1487 throw INTERP_KERNEL::Exception(oss.str().c_str());
1490 nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1491 std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1496 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1497 * For each cell in \b this the number of nodes constituting cell is computed.
1498 * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1499 * So for pohyhedrons some nodes can be counted several times in the returned result.
1501 * \return a newly allocated array
1502 * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1504 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1506 checkConnectivityFullyDefined();
1507 int nbOfCells=getNumberOfCells();
1508 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1509 ret->alloc(nbOfCells,1);
1510 int *retPtr=ret->getPointer();
1511 const int *conn=getNodalConnectivity()->getConstPointer();
1512 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1513 for(int i=0;i<nbOfCells;i++,retPtr++)
1515 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1516 *retPtr=connI[i+1]-connI[i]-1;
1518 *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1524 * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1525 * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1527 * \return DataArrayInt * - new object to be deallocated by the caller.
1528 * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1530 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1532 checkConnectivityFullyDefined();
1533 int nbOfCells=getNumberOfCells();
1534 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1535 ret->alloc(nbOfCells,1);
1536 int *retPtr=ret->getPointer();
1537 const int *conn=getNodalConnectivity()->getConstPointer();
1538 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1539 for(int i=0;i<nbOfCells;i++,retPtr++)
1541 std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1542 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1543 *retPtr=(int)s.size();
1547 *retPtr=(int)s.size();
1554 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1555 * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1557 * \return a newly allocated array
1559 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1561 checkConnectivityFullyDefined();
1562 int nbOfCells=getNumberOfCells();
1563 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1564 ret->alloc(nbOfCells,1);
1565 int *retPtr=ret->getPointer();
1566 const int *conn=getNodalConnectivity()->getConstPointer();
1567 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1568 for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1570 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1571 *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1577 * Removes unused nodes (the node coordinates array is shorten) and returns an array
1578 * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1579 * array mean that the corresponding old node is no more used.
1580 * \return DataArrayInt * - a new instance of DataArrayInt of length \a
1581 * this->getNumberOfNodes() before call of this method. The caller is to
1582 * delete this array using decrRef() as it is no more needed.
1583 * \throw If the coordinates array is not set.
1584 * \throw If the nodal connectivity of cells is not defined.
1585 * \throw If the nodal connectivity includes an invalid id.
1587 * \if ENABLE_EXAMPLES
1588 * \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1589 * \ref py_mcumesh_zipCoordsTraducer "Here is a Python example".
1592 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1594 return MEDCouplingPointSet::zipCoordsTraducer();
1598 * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1599 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1601 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1606 return AreCellsEqual0(conn,connI,cell1,cell2);
1608 return AreCellsEqual1(conn,connI,cell1,cell2);
1610 return AreCellsEqual2(conn,connI,cell1,cell2);
1612 return AreCellsEqual3(conn,connI,cell1,cell2);
1614 return AreCellsEqual7(conn,connI,cell1,cell2);
1616 throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1620 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1622 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1624 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1625 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1630 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1632 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1634 int sz=connI[cell1+1]-connI[cell1];
1635 if(sz==connI[cell2+1]-connI[cell2])
1637 if(conn[connI[cell1]]==conn[connI[cell2]])
1639 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1640 unsigned dim=cm.getDimension();
1646 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1647 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1648 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1649 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1650 return work!=tmp+sz1?1:0;
1653 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1656 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1663 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1665 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1667 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1669 if(conn[connI[cell1]]==conn[connI[cell2]])
1671 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1672 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1680 * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1682 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1684 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1686 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1687 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1694 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1696 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1698 int sz=connI[cell1+1]-connI[cell1];
1699 if(sz==connI[cell2+1]-connI[cell2])
1701 if(conn[connI[cell1]]==conn[connI[cell2]])
1703 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1704 unsigned dim=cm.getDimension();
1710 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1711 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1712 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1713 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1718 std::reverse_iterator<int *> it1((int *)tmp+sz1);
1719 std::reverse_iterator<int *> it2((int *)tmp);
1720 if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1726 return work!=tmp+sz1?1:0;
1729 {//case of SEG2 and SEG3
1730 if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1732 if(!cm.isQuadratic())
1734 std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1735 std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1736 if(std::equal(it1,it2,conn+connI[cell2]+1))
1742 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])
1749 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1756 * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1757 * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1758 * and result remains unchanged.
1759 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1760 * If in 'candidates' pool -1 value is considered as an empty value.
1761 * WARNING this method returns only ONE set of result !
1763 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1765 if(candidates.size()<1)
1768 std::vector<int>::const_iterator iter=candidates.begin();
1769 int start=(*iter++);
1770 for(;iter!=candidates.end();iter++)
1772 int status=AreCellsEqual(conn,connI,start,*iter,compType);
1777 result->pushBackSilent(start);
1781 result->pushBackSilent(*iter);
1783 result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1790 * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1791 * This method keeps the coordiantes of \a this. This method is time consuming and is called
1793 * \param [in] compType input specifying the technique used to compare cells each other.
1794 * - 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.
1795 * - 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)
1796 * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1797 * - 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
1798 * can be used for users not sensitive to orientation of cell
1799 * \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.
1800 * \param [out] commonCells
1801 * \param [out] commonCellsI
1802 * \return the correspondance array old to new in a newly allocated array.
1805 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1807 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1808 getReverseNodalConnectivity(revNodal,revNodalI);
1809 FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1812 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1813 DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr)
1815 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1816 int nbOfCells=nodalI->getNumberOfTuples()-1;
1817 commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1818 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1819 const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1820 std::vector<bool> isFetched(nbOfCells,false);
1823 for(int i=0;i<nbOfCells;i++)
1827 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1828 std::vector<int> v,v2;
1829 if(connOfNode!=connPtr+connIPtr[i+1])
1831 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1832 v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1835 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1839 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1840 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1841 v2.resize(std::distance(v2.begin(),it));
1845 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1847 int pos=commonCellsI->back();
1848 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1849 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1850 isFetched[*it]=true;
1858 for(int i=startCellId;i<nbOfCells;i++)
1862 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1863 std::vector<int> v,v2;
1864 if(connOfNode!=connPtr+connIPtr[i+1])
1866 v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1869 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1873 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1874 v2.resize(std::distance(v2.begin(),it));
1878 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1880 int pos=commonCellsI->back();
1881 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1882 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1883 isFetched[*it]=true;
1889 commonCellsArr=commonCells.retn();
1890 commonCellsIArr=commonCellsI.retn();
1894 * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1895 * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1896 * than \a other->getNumberOfCells() in the returned array means that there is no
1897 * corresponding cell in \a this mesh.
1898 * It is expected that \a this and \a other meshes share the same node coordinates
1899 * array, if it is not so an exception is thrown.
1900 * \param [in] other - the mesh to compare with.
1901 * \param [in] compType - specifies a cell comparison technique. For meaning of its
1902 * valid values [0,1,2], see zipConnectivityTraducer().
1903 * \param [out] arr - a new instance of DataArrayInt returning correspondence
1904 * between cells of the two meshes. It contains \a other->getNumberOfCells()
1905 * values. The caller is to delete this array using
1906 * decrRef() as it is no more needed.
1907 * \return bool - \c true if all cells of \a other mesh are present in the \a this
1910 * \if ENABLE_EXAMPLES
1911 * \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1912 * \ref py_mcumesh_areCellsIncludedIn "Here is a Python example".
1914 * \sa checkDeepEquivalOnSameNodesWith()
1915 * \sa checkGeoEquivalWith()
1917 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1919 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1920 int nbOfCells=getNumberOfCells();
1921 static const int possibleCompType[]={0,1,2};
1922 if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1924 std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1925 std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1927 throw INTERP_KERNEL::Exception(oss.str().c_str());
1929 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1930 arr=o2n->substr(nbOfCells);
1931 arr->setName(other->getName());
1933 if(other->getNumberOfCells()==0)
1935 return arr->getMaxValue(tmp)<nbOfCells;
1939 * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1940 * This method tries to determine if \b other is fully included in \b this.
1941 * The main difference is that this method is not expected to throw exception.
1942 * This method has two outputs :
1944 * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1945 * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1947 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1949 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1950 DataArrayInt *commonCells=0,*commonCellsI=0;
1951 int thisNbCells=getNumberOfCells();
1952 mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1953 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1954 const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1955 int otherNbCells=other->getNumberOfCells();
1956 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1957 arr2->alloc(otherNbCells,1);
1958 arr2->fillWithZero();
1959 int *arr2Ptr=arr2->getPointer();
1960 int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1961 for(int i=0;i<nbOfCommon;i++)
1963 int start=commonCellsPtr[commonCellsIPtr[i]];
1964 if(start<thisNbCells)
1966 for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1968 int sig=commonCellsPtr[j]>0?1:-1;
1969 int val=std::abs(commonCellsPtr[j])-1;
1970 if(val>=thisNbCells)
1971 arr2Ptr[val-thisNbCells]=sig*(start+1);
1975 arr2->setName(other->getName());
1976 if(arr2->presenceOfValue(0))
1982 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1985 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1986 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1988 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1989 std::vector<const MEDCouplingUMesh *> ms(2);
1992 return MergeUMeshesOnSameCoords(ms);
1996 * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1997 * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1998 * cellIds is not given explicitely but by a range python like.
2000 * \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.
2001 * \return a newly allocated
2003 * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
2004 * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
2006 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const
2008 if(getMeshDimension()!=-1)
2009 return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
2012 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
2014 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2016 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2018 return const_cast<MEDCouplingUMesh *>(this);
2023 * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
2024 * The result mesh shares or not the node coordinates array with \a this mesh depending
2025 * on \a keepCoords parameter.
2026 * \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
2027 * to write this mesh to the MED file, its cells must be sorted using
2028 * sortCellsInMEDFileFrmt().
2029 * \param [in] begin - an array of cell ids to include to the new mesh.
2030 * \param [in] end - a pointer to last-plus-one-th element of \a begin.
2031 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2032 * array of \a this mesh, else "free" nodes are removed from the result mesh
2033 * by calling zipCoords().
2034 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2035 * to delete this mesh using decrRef() as it is no more needed.
2036 * \throw If the coordinates array is not set.
2037 * \throw If the nodal connectivity of cells is not defined.
2038 * \throw If any cell id in the array \a begin is not valid.
2040 * \if ENABLE_EXAMPLES
2041 * \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
2042 * \ref py_mcumesh_buildPartOfMySelf "Here is a Python example".
2045 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2047 if(getMeshDimension()!=-1)
2048 return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
2052 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2054 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2056 return const_cast<MEDCouplingUMesh *>(this);
2061 * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2063 * 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.
2064 * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2065 * The number of cells of \b this will remain the same with this method.
2067 * \param [in] begin begin of cell ids (included) of cells in this to assign
2068 * \param [in] end end of cell ids (excluded) of cells in this to assign
2069 * \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 ).
2070 * Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2072 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2074 checkConnectivityFullyDefined();
2075 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2076 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2077 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2078 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2080 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2081 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2082 throw INTERP_KERNEL::Exception(oss.str().c_str());
2084 int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2085 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2087 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2088 throw INTERP_KERNEL::Exception(oss.str().c_str());
2090 int nbOfCells=getNumberOfCells();
2091 bool easyAssign=true;
2092 const int *connI=_nodal_connec_index->getConstPointer();
2093 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2094 for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2096 if(*it>=0 && *it<nbOfCells)
2098 easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2102 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2103 throw INTERP_KERNEL::Exception(oss.str().c_str());
2108 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2113 DataArrayInt *arrOut=0,*arrIOut=0;
2114 MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2116 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2117 setConnectivity(arrOut,arrIOut,true);
2121 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2123 checkConnectivityFullyDefined();
2124 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2125 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2126 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2127 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2129 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2130 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2131 throw INTERP_KERNEL::Exception(oss.str().c_str());
2133 int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2134 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2136 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2137 throw INTERP_KERNEL::Exception(oss.str().c_str());
2139 int nbOfCells=getNumberOfCells();
2140 bool easyAssign=true;
2141 const int *connI=_nodal_connec_index->getConstPointer();
2142 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2144 for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2146 if(it>=0 && it<nbOfCells)
2148 easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2152 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2153 throw INTERP_KERNEL::Exception(oss.str().c_str());
2158 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2163 DataArrayInt *arrOut=0,*arrIOut=0;
2164 MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2166 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2167 setConnectivity(arrOut,arrIOut,true);
2172 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2173 * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2174 * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2175 * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2177 * \param [in] begin input start of array of node ids.
2178 * \param [in] end input end of array of node ids.
2179 * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2180 * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2182 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2184 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2185 checkConnectivityFullyDefined();
2187 int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2188 std::vector<bool> fastFinder(sz,false);
2189 for(const int *work=begin;work!=end;work++)
2190 if(*work>=0 && *work<sz)
2191 fastFinder[*work]=true;
2192 int nbOfCells=getNumberOfCells();
2193 const int *conn=getNodalConnectivity()->getConstPointer();
2194 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2195 for(int i=0;i<nbOfCells;i++)
2197 int ref=0,nbOfHit=0;
2198 for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2202 if(fastFinder[*work2])
2205 if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2206 cellIdsKept->pushBackSilent(i);
2208 cellIdsKeptArr=cellIdsKept.retn();
2212 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2213 * this->getMeshDimension(), that bound some cells of \a this mesh.
2214 * The cells of lower dimension to include to the result mesh are selected basing on
2215 * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2216 * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2217 * ==\c false, a cell is copied if any its node is in the array of node ids. The
2218 * created mesh shares the node coordinates array with \a this mesh.
2219 * \param [in] begin - the array of node ids.
2220 * \param [in] end - a pointer to the (last+1)-th element of \a begin.
2221 * \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2222 * array \a begin are added, else cells whose any node is in the
2223 * array \a begin are added.
2224 * \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2225 * to delete this mesh using decrRef() as it is no more needed.
2226 * \throw If the coordinates array is not set.
2227 * \throw If the nodal connectivity of cells is not defined.
2228 * \throw If any node id in \a begin is not valid.
2230 * \if ENABLE_EXAMPLES
2231 * \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2232 * \ref py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2235 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2237 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2238 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2239 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2240 desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2241 return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2245 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2246 * this->getMeshDimension(), which bound only one cell of \a this mesh.
2247 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2248 * array of \a this mesh, else "free" nodes are removed from the result mesh
2249 * by calling zipCoords().
2250 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2251 * to delete this mesh using decrRef() as it is no more needed.
2252 * \throw If the coordinates array is not set.
2253 * \throw If the nodal connectivity of cells is not defined.
2255 * \if ENABLE_EXAMPLES
2256 * \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2257 * \ref py_mcumesh_buildBoundaryMesh "Here is a Python example".
2260 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2262 DataArrayInt *desc=DataArrayInt::New();
2263 DataArrayInt *descIndx=DataArrayInt::New();
2264 DataArrayInt *revDesc=DataArrayInt::New();
2265 DataArrayInt *revDescIndx=DataArrayInt::New();
2267 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2270 descIndx->decrRef();
2271 int nbOfCells=meshDM1->getNumberOfCells();
2272 const int *revDescIndxC=revDescIndx->getConstPointer();
2273 std::vector<int> boundaryCells;
2274 for(int i=0;i<nbOfCells;i++)
2275 if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2276 boundaryCells.push_back(i);
2277 revDescIndx->decrRef();
2278 MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2283 * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2284 * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2285 * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown.
2287 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2289 checkFullyDefined();
2290 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2291 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2292 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2293 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2295 buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2296 desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2298 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2299 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2300 const int *revDescPtr=revDesc->getConstPointer();
2301 const int *revDescIndxPtr=revDescIndx->getConstPointer();
2302 int nbOfCells=getNumberOfCells();
2303 std::vector<bool> ret1(nbOfCells,false);
2305 for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2306 if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2307 { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2309 DataArrayInt *ret2=DataArrayInt::New();
2311 int *ret2Ptr=ret2->getPointer();
2313 for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2316 ret2->setName("BoundaryCells");
2321 * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2322 * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2323 * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2324 * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2326 * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2327 * This method method returns cells ids set s = s1 + s2 where :
2329 * - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2330 * - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2332 * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2333 * are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2335 * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2336 * \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
2337 * cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2339 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2341 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2342 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2343 checkConnectivityFullyDefined();
2344 otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2345 if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2346 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2347 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2348 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2349 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2350 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2351 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2352 const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2353 DataArrayInt *idsOtherInConsti=0;
2354 bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2355 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2357 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2359 for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2360 s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2361 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2362 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2363 DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2364 ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2365 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2366 ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2367 neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2368 RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2369 neighThisPartAuto=0;
2370 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2371 const int li[2]={0,1};
2372 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2373 s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2374 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2377 cellIdsRk0=s0arr.retn();
2378 cellIdsRk1=s_renum1.retn();
2382 * 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
2383 * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2385 * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2387 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2389 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2390 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2391 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2392 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2394 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2395 revDesc=0; desc=0; descIndx=0;
2396 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2397 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2398 return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2402 * Finds nodes lying on the boundary of \a this mesh.
2403 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2404 * nodes. The caller is to delete this array using decrRef() as it is no
2406 * \throw If the coordinates array is not set.
2407 * \throw If the nodal connectivity of cells is node defined.
2409 * \if ENABLE_EXAMPLES
2410 * \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2411 * \ref py_mcumesh_findBoundaryNodes "Here is a Python example".
2414 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2416 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2417 return skin->computeFetchedNodeIds();
2420 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2423 return const_cast<MEDCouplingUMesh *>(this);
2427 * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2428 * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2429 * 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.
2430 * 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.
2431 * 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.
2433 * \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
2434 * parameter is altered during the call.
2435 * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2436 * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2437 * \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.
2439 * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2441 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2442 DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const
2444 checkFullyDefined();
2445 otherDimM1OnSameCoords.checkFullyDefined();
2446 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2447 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2448 if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2449 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2450 DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2451 findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2452 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2453 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2454 s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2455 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2456 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2457 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2458 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2459 cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2461 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2462 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2463 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2464 DataArrayInt *idsTmp=0;
2465 bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2466 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2468 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2469 MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2470 DataArrayInt *tmp0=0,*tmp1=0;
2471 ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2472 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2473 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2474 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2475 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2476 cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2477 cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2479 cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2480 cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2481 nodeIdsToDuplicate=s3.retn();
2485 * This method operates a modification of the connectivity and coords in \b this.
2486 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2487 * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2488 * 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
2489 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2490 * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2492 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2494 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2495 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2497 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2499 int nbOfNodes=getNumberOfNodes();
2500 duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2501 duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2505 * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2506 * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2507 * This method is a generalization of shiftNodeNumbersInConn().
2508 * \warning This method performs no check of validity of new ids. **Use it with care !**
2509 * \param [in] newNodeNumbersO2N - a permutation array, of length \a
2510 * this->getNumberOfNodes(), in "Old to New" mode.
2511 * See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2512 * \throw If the nodal connectivity of cells is not defined.
2514 * \if ENABLE_EXAMPLES
2515 * \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2516 * \ref py_mcumesh_renumberNodesInConn "Here is a Python example".
2519 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2521 checkConnectivityFullyDefined();
2522 int *conn=getNodalConnectivity()->getPointer();
2523 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2524 int nbOfCells=getNumberOfCells();
2525 for(int i=0;i<nbOfCells;i++)
2526 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2528 int& node=conn[iconn];
2529 if(node>=0)//avoid polyhedron separator
2531 node=newNodeNumbersO2N[node];
2534 _nodal_connec->declareAsNew();
2539 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2540 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2541 * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2543 * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2545 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2547 checkConnectivityFullyDefined();
2548 int *conn=getNodalConnectivity()->getPointer();
2549 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2550 int nbOfCells=getNumberOfCells();
2551 for(int i=0;i<nbOfCells;i++)
2552 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2554 int& node=conn[iconn];
2555 if(node>=0)//avoid polyhedron separator
2560 _nodal_connec->declareAsNew();
2565 * This method operates a modification of the connectivity in \b this.
2566 * 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.
2567 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2568 * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2569 * 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
2570 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2571 * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2573 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2574 * As an another consequense after the call of this method \b this can be transiently non cohrent.
2576 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2577 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2578 * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ).
2580 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2582 checkConnectivityFullyDefined();
2583 std::map<int,int> m;
2585 for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2587 int *conn=getNodalConnectivity()->getPointer();
2588 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2589 int nbOfCells=getNumberOfCells();
2590 for(int i=0;i<nbOfCells;i++)
2591 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2593 int& node=conn[iconn];
2594 if(node>=0)//avoid polyhedron separator
2596 std::map<int,int>::iterator it=m.find(node);
2605 * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2607 * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2608 * After the call of this method the number of cells remains the same as before.
2610 * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2611 * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2612 * be strictly in [0;this->getNumberOfCells()).
2614 * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2615 * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2616 * should be contained in[0;this->getNumberOfCells()).
2618 * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2620 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2622 checkConnectivityFullyDefined();
2623 int nbCells=getNumberOfCells();
2624 const int *array=old2NewBg;
2626 array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2628 const int *conn=_nodal_connec->getConstPointer();
2629 const int *connI=_nodal_connec_index->getConstPointer();
2630 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2631 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2632 const int *n2oPtr=n2o->begin();
2633 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2634 newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2635 newConn->copyStringInfoFrom(*_nodal_connec);
2636 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2637 newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2638 newConnI->copyStringInfoFrom(*_nodal_connec_index);
2640 int *newC=newConn->getPointer();
2641 int *newCI=newConnI->getPointer();
2644 for(int i=0;i<nbCells;i++)
2647 int nbOfElts=connI[pos+1]-connI[pos];
2648 newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2653 setConnectivity(newConn,newConnI);
2655 free(const_cast<int *>(array));
2659 * Finds cells whose bounding boxes intersect a given bounding box.
2660 * \param [in] bbox - an array defining the bounding box via coordinates of its
2661 * extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2663 * \param [in] eps - a factor used to increase size of the bounding box of cell
2664 * before comparing it with \a bbox. This factor is multiplied by the maximal
2665 * extent of the bounding box of cell to produce an addition to this bounding box.
2666 * \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2667 * cells. The caller is to delete this array using decrRef() as it is no more
2669 * \throw If the coordinates array is not set.
2670 * \throw If the nodal connectivity of cells is not defined.
2672 * \if ENABLE_EXAMPLES
2673 * \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2674 * \ref py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2677 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2679 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2680 if(getMeshDimension()==-1)
2682 elems->pushBackSilent(0);
2683 return elems.retn();
2685 int dim=getSpaceDimension();
2686 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2687 const int* conn = getNodalConnectivity()->getConstPointer();
2688 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2689 const double* coords = getCoords()->getConstPointer();
2690 int nbOfCells=getNumberOfCells();
2691 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2693 for (int i=0; i<dim; i++)
2695 elem_bb[i*2]=std::numeric_limits<double>::max();
2696 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2699 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2701 int node= conn[inode];
2702 if(node>=0)//avoid polyhedron separator
2704 for (int idim=0; idim<dim; idim++)
2706 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2708 elem_bb[idim*2] = coords[node*dim+idim] ;
2710 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2712 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2717 if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2718 elems->pushBackSilent(ielem);
2720 return elems.retn();
2724 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2725 * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2726 * added in 'elems' parameter.
2728 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2730 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2731 if(getMeshDimension()==-1)
2733 elems->pushBackSilent(0);
2734 return elems.retn();
2736 int dim=getSpaceDimension();
2737 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2738 const int* conn = getNodalConnectivity()->getConstPointer();
2739 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2740 const double* coords = getCoords()->getConstPointer();
2741 int nbOfCells=getNumberOfCells();
2742 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2744 for (int i=0; i<dim; i++)
2746 elem_bb[i*2]=std::numeric_limits<double>::max();
2747 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2750 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2752 int node= conn[inode];
2753 if(node>=0)//avoid polyhedron separator
2755 for (int idim=0; idim<dim; idim++)
2757 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2759 elem_bb[idim*2] = coords[node*dim+idim] ;
2761 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2763 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2768 if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2769 elems->pushBackSilent(ielem);
2771 return elems.retn();
2775 * Returns a type of a cell by its id.
2776 * \param [in] cellId - the id of the cell of interest.
2777 * \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2778 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2780 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2782 const int *ptI=_nodal_connec_index->getConstPointer();
2783 const int *pt=_nodal_connec->getConstPointer();
2784 if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2785 return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2788 std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2789 throw INTERP_KERNEL::Exception(oss.str().c_str());
2794 * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2795 * This method does not throw exception if geometric type \a type is not in \a this.
2796 * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2797 * The coordinates array is not considered here.
2799 * \param [in] type the geometric type
2800 * \return cell ids in this having geometric type \a type.
2802 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2805 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2807 checkConnectivityFullyDefined();
2808 int nbCells=getNumberOfCells();
2809 int mdim=getMeshDimension();
2810 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2811 if(mdim!=(int)cm.getDimension())
2812 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2813 const int *ptI=_nodal_connec_index->getConstPointer();
2814 const int *pt=_nodal_connec->getConstPointer();
2815 for(int i=0;i<nbCells;i++)
2817 if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2818 ret->pushBackSilent(i);
2824 * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2826 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2828 const int *ptI=_nodal_connec_index->getConstPointer();
2829 const int *pt=_nodal_connec->getConstPointer();
2830 int nbOfCells=getNumberOfCells();
2832 for(int i=0;i<nbOfCells;i++)
2833 if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2839 * Returns the nodal connectivity of a given cell.
2840 * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2841 * all returned node ids can be used in getCoordinatesOfNode().
2842 * \param [in] cellId - an id of the cell of interest.
2843 * \param [in,out] conn - a vector where the node ids are appended. It is not
2844 * cleared before the appending.
2845 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2847 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2849 const int *ptI=_nodal_connec_index->getConstPointer();
2850 const int *pt=_nodal_connec->getConstPointer();
2851 for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2856 std::string MEDCouplingUMesh::simpleRepr() const
2858 static const char msg0[]="No coordinates specified !";
2859 std::ostringstream ret;
2860 ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2861 ret << "Description of mesh : \"" << getDescription() << "\"\n";
2863 double tt=getTime(tmpp1,tmpp2);
2864 ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2865 ret << "Iteration : " << tmpp1 << " Order : " << tmpp2 << "\n";
2867 { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2869 { ret << " Mesh dimension has not been set or is invalid !"; }
2872 const int spaceDim=getSpaceDimension();
2873 ret << spaceDim << "\nInfo attached on space dimension : ";
2874 for(int i=0;i<spaceDim;i++)
2875 ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2879 ret << msg0 << "\n";
2880 ret << "Number of nodes : ";
2882 ret << getNumberOfNodes() << "\n";
2884 ret << msg0 << "\n";
2885 ret << "Number of cells : ";
2886 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2887 ret << getNumberOfCells() << "\n";
2889 ret << "No connectivity specified !" << "\n";
2890 ret << "Cell types present : ";
2891 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2893 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2894 ret << cm.getRepr() << " ";
2900 std::string MEDCouplingUMesh::advancedRepr() const
2902 std::ostringstream ret;
2903 ret << simpleRepr();
2904 ret << "\nCoordinates array : \n___________________\n\n";
2906 _coords->reprWithoutNameStream(ret);
2908 ret << "No array set !\n";
2909 ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2910 reprConnectivityOfThisLL(ret);
2915 * This method returns a C++ code that is a dump of \a this.
2916 * This method will throw if this is not fully defined.
2918 std::string MEDCouplingUMesh::cppRepr() const
2920 static const char coordsName[]="coords";
2921 static const char connName[]="conn";
2922 static const char connIName[]="connI";
2923 checkFullyDefined();
2924 std::ostringstream ret; ret << "// coordinates" << std::endl;
2925 _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2926 _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2927 _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2928 ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2929 ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2930 ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2931 ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2935 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2937 std::ostringstream ret;
2938 reprConnectivityOfThisLL(ret);
2943 * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
2944 * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2945 * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2948 * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2949 * 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
2950 * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2952 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
2954 int mdim=getMeshDimension();
2956 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2957 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
2958 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
2959 bool needToCpyCT=true;
2962 tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2970 if(!_nodal_connec_index)
2972 tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2977 tmp2=_nodal_connec_index;
2980 ret->setConnectivity(tmp1,tmp2,false);
2985 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2986 ret->setCoords(coords);
2989 ret->setCoords(_coords);
2993 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
2995 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2997 int nbOfCells=getNumberOfCells();
2998 const int *c=_nodal_connec->getConstPointer();
2999 const int *ci=_nodal_connec_index->getConstPointer();
3000 for(int i=0;i<nbOfCells;i++)
3002 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3003 stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3004 std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3009 stream << "Connectivity not defined !\n";
3012 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3014 const int *ptI=_nodal_connec_index->getConstPointer();
3015 const int *pt=_nodal_connec->getConstPointer();
3016 if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3017 return ptI[cellId+1]-ptI[cellId]-1;
3019 return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3023 * Returns types of cells of the specified part of \a this mesh.
3024 * This method avoids computing sub-mesh explicitely to get its types.
3025 * \param [in] begin - an array of cell ids of interest.
3026 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3027 * \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3028 * describing the cell types.
3029 * \throw If the coordinates array is not set.
3030 * \throw If the nodal connectivity of cells is not defined.
3031 * \sa getAllGeoTypes()
3033 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3035 checkFullyDefined();
3036 std::set<INTERP_KERNEL::NormalizedCellType> ret;
3037 const int *conn=_nodal_connec->getConstPointer();
3038 const int *connIndex=_nodal_connec_index->getConstPointer();
3039 for(const int *w=begin;w!=end;w++)
3040 ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3045 * Defines the nodal connectivity using given connectivity arrays. Optionally updates
3046 * a set of types of cells constituting \a this mesh.
3047 * This method is for advanced users having prepared their connectivity before. For
3048 * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3049 * \param [in] conn - the nodal connectivity array.
3050 * \param [in] connIndex - the nodal connectivity index array.
3051 * \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3054 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3056 DataArrayInt::SetArrayIn(conn,_nodal_connec);
3057 DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3058 if(isComputingTypes)
3064 * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
3065 * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3067 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3068 _nodal_connec(0),_nodal_connec_index(0),
3069 _types(other._types)
3071 if(other._nodal_connec)
3072 _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3073 if(other._nodal_connec_index)
3074 _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3077 MEDCouplingUMesh::~MEDCouplingUMesh()
3080 _nodal_connec->decrRef();
3081 if(_nodal_connec_index)
3082 _nodal_connec_index->decrRef();
3086 * Recomputes a set of cell types of \a this mesh. For more info see
3087 * \ref MEDCouplingUMeshNodalConnectivity.
3089 void MEDCouplingUMesh::computeTypes()
3091 if(_nodal_connec && _nodal_connec_index)
3094 const int *conn=_nodal_connec->getConstPointer();
3095 const int *connIndex=_nodal_connec_index->getConstPointer();
3096 int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
3098 for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
3099 _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
3104 * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3106 void MEDCouplingUMesh::checkFullyDefined() const
3108 if(!_nodal_connec_index || !_nodal_connec || !_coords)
3109 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3113 * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3115 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3117 if(!_nodal_connec_index || !_nodal_connec)
3118 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3122 * Returns a number of cells constituting \a this mesh.
3123 * \return int - the number of cells in \a this mesh.
3124 * \throw If the nodal connectivity of cells is not defined.
3126 int MEDCouplingUMesh::getNumberOfCells() const
3128 if(_nodal_connec_index)
3129 return _nodal_connec_index->getNumberOfTuples()-1;
3134 throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3138 * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3139 * mesh. For more info see \ref MEDCouplingMeshesPage.
3140 * \return int - the dimension of \a this mesh.
3141 * \throw If the mesh dimension is not defined using setMeshDimension().
3143 int MEDCouplingUMesh::getMeshDimension() const
3146 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3151 * Returns a length of the nodal connectivity array.
3152 * This method is for test reason. Normally the integer returned is not useable by
3153 * user. For more info see \ref MEDCouplingUMeshNodalConnectivity.
3154 * \return int - the length of the nodal connectivity array.
3156 int MEDCouplingUMesh::getMeshLength() const
3158 return _nodal_connec->getNbOfElems();
3162 * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3164 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3166 MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3167 tinyInfo.push_back(getMeshDimension());
3168 tinyInfo.push_back(getNumberOfCells());
3170 tinyInfo.push_back(getMeshLength());
3172 tinyInfo.push_back(-1);
3176 * First step of unserialization process.
3178 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3180 return tinyInfo[6]<=0;
3184 * Second step of serialization process.
3185 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3187 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3189 MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3191 a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3195 * Third and final step of serialization process.
3197 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3199 MEDCouplingPointSet::serialize(a1,a2);
3200 if(getMeshDimension()>-1)
3202 a1=DataArrayInt::New();
3203 a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3204 int *ptA1=a1->getPointer();
3205 const int *conn=getNodalConnectivity()->getConstPointer();
3206 const int *index=getNodalConnectivityIndex()->getConstPointer();
3207 ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3208 std::copy(conn,conn+getMeshLength(),ptA1);
3215 * Second and final unserialization process.
3216 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3218 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3220 MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3221 setMeshDimension(tinyInfo[5]);
3225 const int *recvBuffer=a1->getConstPointer();
3226 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3227 myConnecIndex->alloc(tinyInfo[6]+1,1);
3228 std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3229 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3230 myConnec->alloc(tinyInfo[7],1);
3231 std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3232 setConnectivity(myConnec, myConnecIndex);
3237 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3238 * CellIds are given using range specified by a start an end and step.
3240 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3242 checkFullyDefined();
3243 int ncell=getNumberOfCells();
3244 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3245 ret->_mesh_dim=_mesh_dim;
3246 ret->setCoords(_coords);
3247 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3248 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3249 int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3251 const int *conn=_nodal_connec->getConstPointer();
3252 const int *connIndex=_nodal_connec_index->getConstPointer();
3253 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3255 if(work>=0 && work<ncell)
3257 newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3261 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3262 throw INTERP_KERNEL::Exception(oss.str().c_str());
3265 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3266 int *newConnPtr=newConn->getPointer();
3267 std::set<INTERP_KERNEL::NormalizedCellType> types;
3269 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3271 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3272 newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3274 ret->setConnectivity(newConn,newConnI,false);
3276 ret->copyTinyInfoFrom(this);
3281 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3282 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3283 * The return newly allocated mesh will share the same coordinates as \a this.
3285 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3287 checkConnectivityFullyDefined();
3288 int ncell=getNumberOfCells();
3289 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3290 ret->_mesh_dim=_mesh_dim;
3291 ret->setCoords(_coords);
3292 std::size_t nbOfElemsRet=std::distance(begin,end);
3293 int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3295 const int *conn=_nodal_connec->getConstPointer();
3296 const int *connIndex=_nodal_connec_index->getConstPointer();
3298 for(const int *work=begin;work!=end;work++,newNbring++)
3300 if(*work>=0 && *work<ncell)
3301 connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3305 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3306 throw INTERP_KERNEL::Exception(oss.str().c_str());
3309 int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3310 int *connRetWork=connRet;
3311 std::set<INTERP_KERNEL::NormalizedCellType> types;
3312 for(const int *work=begin;work!=end;work++)
3314 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3315 connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3317 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3318 connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3319 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3320 connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3321 ret->setConnectivity(connRetArr,connIndexRetArr,false);
3323 ret->copyTinyInfoFrom(this);
3328 * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3330 * For 1D cells, the returned field contains lengths.<br>
3331 * For 2D cells, the returned field contains areas.<br>
3332 * For 3D cells, the returned field contains volumes.
3333 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3334 * orientation, i.e. the volume is always positive.
3335 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3336 * and one time . The caller is to delete this field using decrRef() as it is no
3339 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3341 std::string name="MeasureOfMesh_";
3343 int nbelem=getNumberOfCells();
3344 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3345 field->setName(name);
3346 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3347 array->alloc(nbelem,1);
3348 double *area_vol=array->getPointer();
3349 field->setArray(array) ; array=0;
3350 field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3351 field->synchronizeTimeWithMesh();
3352 if(getMeshDimension()!=-1)
3355 INTERP_KERNEL::NormalizedCellType type;
3356 int dim_space=getSpaceDimension();
3357 const double *coords=getCoords()->getConstPointer();
3358 const int *connec=getNodalConnectivity()->getConstPointer();
3359 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3360 for(int iel=0;iel<nbelem;iel++)
3362 ipt=connec_index[iel];
3363 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3364 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);
3367 std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3371 area_vol[0]=std::numeric_limits<double>::max();
3373 return field.retn();
3377 * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3379 * For 1D cells, the returned array contains lengths.<br>
3380 * For 2D cells, the returned array contains areas.<br>
3381 * For 3D cells, the returned array contains volumes.
3382 * This method avoids building explicitly a part of \a this mesh to perform the work.
3383 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3384 * orientation, i.e. the volume is always positive.
3385 * \param [in] begin - an array of cell ids of interest.
3386 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3387 * \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3388 * delete this array using decrRef() as it is no more needed.
3390 * \if ENABLE_EXAMPLES
3391 * \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3392 * \ref py_mcumesh_getPartMeasureField "Here is a Python example".
3394 * \sa getMeasureField()
3396 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3398 std::string name="PartMeasureOfMesh_";
3400 int nbelem=(int)std::distance(begin,end);
3401 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3402 array->setName(name);
3403 array->alloc(nbelem,1);
3404 double *area_vol=array->getPointer();
3405 if(getMeshDimension()!=-1)
3408 INTERP_KERNEL::NormalizedCellType type;
3409 int dim_space=getSpaceDimension();
3410 const double *coords=getCoords()->getConstPointer();
3411 const int *connec=getNodalConnectivity()->getConstPointer();
3412 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3413 for(const int *iel=begin;iel!=end;iel++)
3415 ipt=connec_index[*iel];
3416 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3417 *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3420 std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3424 area_vol[0]=std::numeric_limits<double>::max();
3426 return array.retn();
3430 * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3431 * \a this one. The returned field contains the dual cell volume for each corresponding
3432 * node in \a this mesh. In other words, the field returns the getMeasureField() of
3433 * the dual mesh in P1 sens of \a this.<br>
3434 * For 1D cells, the returned field contains lengths.<br>
3435 * For 2D cells, the returned field contains areas.<br>
3436 * For 3D cells, the returned field contains volumes.
3437 * This method is useful to check "P1*" conservative interpolators.
3438 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3439 * orientation, i.e. the volume is always positive.
3440 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3441 * nodes and one time. The caller is to delete this array using decrRef() as
3442 * it is no more needed.
3444 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3446 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3447 std::string name="MeasureOnNodeOfMesh_";
3449 int nbNodes=getNumberOfNodes();
3450 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3451 double cst=1./((double)getMeshDimension()+1.);
3452 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3453 array->alloc(nbNodes,1);
3454 double *valsToFill=array->getPointer();
3455 std::fill(valsToFill,valsToFill+nbNodes,0.);
3456 const double *values=tmp->getArray()->getConstPointer();
3457 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3458 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3459 getReverseNodalConnectivity(da,daInd);
3460 const int *daPtr=da->getConstPointer();
3461 const int *daIPtr=daInd->getConstPointer();
3462 for(int i=0;i<nbNodes;i++)
3463 for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3464 valsToFill[i]+=cst*values[*cell];
3466 ret->setArray(array);
3471 * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3472 * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3473 * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3474 * and are normalized.
3475 * <br> \a this can be either
3476 * - a 2D mesh in 2D or 3D space or
3477 * - an 1D mesh in 2D space.
3479 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3480 * cells and one time. The caller is to delete this field using decrRef() as
3481 * it is no more needed.
3482 * \throw If the nodal connectivity of cells is not defined.
3483 * \throw If the coordinates array is not set.
3484 * \throw If the mesh dimension is not set.
3485 * \throw If the mesh and space dimension is not as specified above.
3487 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3489 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3490 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3491 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3492 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3493 int nbOfCells=getNumberOfCells();
3494 int nbComp=getMeshDimension()+1;
3495 array->alloc(nbOfCells,nbComp);
3496 double *vals=array->getPointer();
3497 const int *connI=_nodal_connec_index->getConstPointer();
3498 const int *conn=_nodal_connec->getConstPointer();
3499 const double *coords=_coords->getConstPointer();
3500 if(getMeshDimension()==2)
3502 if(getSpaceDimension()==3)
3504 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3505 const double *locPtr=loc->getConstPointer();
3506 for(int i=0;i<nbOfCells;i++,vals+=3)
3508 int offset=connI[i];
3509 INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3510 double n=INTERP_KERNEL::norm<3>(vals);
3511 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3516 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3517 const double *isAbsPtr=isAbs->getArray()->begin();
3518 for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3519 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3522 else//meshdimension==1
3525 for(int i=0;i<nbOfCells;i++)
3527 int offset=connI[i];
3528 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3529 double n=INTERP_KERNEL::norm<2>(tmp);
3530 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3535 ret->setArray(array);
3537 ret->synchronizeTimeWithSupport();
3542 * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3543 * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3544 * and are normalized.
3545 * <br> \a this can be either
3546 * - a 2D mesh in 2D or 3D space or
3547 * - an 1D mesh in 2D space.
3549 * This method avoids building explicitly a part of \a this mesh to perform the work.
3550 * \param [in] begin - an array of cell ids of interest.
3551 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3552 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3553 * cells and one time. The caller is to delete this field using decrRef() as
3554 * it is no more needed.
3555 * \throw If the nodal connectivity of cells is not defined.
3556 * \throw If the coordinates array is not set.
3557 * \throw If the mesh dimension is not set.
3558 * \throw If the mesh and space dimension is not as specified above.
3559 * \sa buildOrthogonalField()
3561 * \if ENABLE_EXAMPLES
3562 * \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3563 * \ref py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3566 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3568 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3569 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3570 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3571 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3572 std::size_t nbelems=std::distance(begin,end);
3573 int nbComp=getMeshDimension()+1;
3574 array->alloc((int)nbelems,nbComp);
3575 double *vals=array->getPointer();
3576 const int *connI=_nodal_connec_index->getConstPointer();
3577 const int *conn=_nodal_connec->getConstPointer();
3578 const double *coords=_coords->getConstPointer();
3579 if(getMeshDimension()==2)
3581 if(getSpaceDimension()==3)
3583 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3584 const double *locPtr=loc->getConstPointer();
3585 for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3587 int offset=connI[*i];
3588 INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3589 double n=INTERP_KERNEL::norm<3>(vals);
3590 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3595 for(std::size_t i=0;i<nbelems;i++)
3596 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3599 else//meshdimension==1
3602 for(const int *i=begin;i!=end;i++)
3604 int offset=connI[*i];
3605 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3606 double n=INTERP_KERNEL::norm<2>(tmp);
3607 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3612 ret->setArray(array);
3614 ret->synchronizeTimeWithSupport();
3619 * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3620 * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3621 * and are \b not normalized.
3622 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3623 * cells and one time. The caller is to delete this field using decrRef() as
3624 * it is no more needed.
3625 * \throw If the nodal connectivity of cells is not defined.
3626 * \throw If the coordinates array is not set.
3627 * \throw If \a this->getMeshDimension() != 1.
3628 * \throw If \a this mesh includes cells of type other than SEG2.
3630 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3632 if(getMeshDimension()!=1)
3633 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3634 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3635 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3636 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3637 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3638 int nbOfCells=getNumberOfCells();
3639 int spaceDim=getSpaceDimension();
3640 array->alloc(nbOfCells,spaceDim);
3641 double *pt=array->getPointer();
3642 const double *coo=getCoords()->getConstPointer();
3643 std::vector<int> conn;
3645 for(int i=0;i<nbOfCells;i++)
3648 getNodeIdsOfCell(i,conn);
3649 pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3651 ret->setArray(array);
3653 ret->synchronizeTimeWithSupport();
3658 * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3659 * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3660 * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3661 * from. If a result face is shared by two 3D cells, then the face in included twice in
3663 * \param [in] origin - 3 components of a point defining location of the plane.
3664 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3665 * must be greater than 1e-6.
3666 * \param [in] eps - half-thickness of the plane.
3667 * \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3668 * producing correspondent 2D cells. The caller is to delete this array
3669 * using decrRef() as it is no more needed.
3670 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3671 * not share the node coordinates array with \a this mesh. The caller is to
3672 * delete this mesh using decrRef() as it is no more needed.
3673 * \throw If the coordinates array is not set.
3674 * \throw If the nodal connectivity of cells is not defined.
3675 * \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3676 * \throw If magnitude of \a vec is less than 1e-6.
3677 * \throw If the plane does not intersect any 3D cell of \a this mesh.
3678 * \throw If \a this includes quadratic cells.
3680 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3682 checkFullyDefined();
3683 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3684 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3685 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3686 if(candidates->empty())
3687 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3688 std::vector<int> nodes;
3689 DataArrayInt *cellIds1D=0;
3690 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3691 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3692 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3693 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3694 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3695 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3696 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3697 revDesc2=0; revDescIndx2=0;
3698 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3699 revDesc1=0; revDescIndx1=0;
3700 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3701 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3703 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3704 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3706 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3707 std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3708 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3709 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3710 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3711 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3712 connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3713 subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3714 if(cellIds2->empty())
3715 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3716 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3717 ret->setCoords(mDesc1->getCoords());
3718 ret->setConnectivity(conn,connI,true);
3719 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3724 * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3725 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
3726 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3728 * \param [in] origin - 3 components of a point defining location of the plane.
3729 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3730 * must be greater than 1e-6.
3731 * \param [in] eps - half-thickness of the plane.
3732 * \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3733 * producing correspondent segments. The caller is to delete this array
3734 * using decrRef() as it is no more needed.
3735 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3736 * mesh in 3D space. This mesh does not share the node coordinates array with
3737 * \a this mesh. The caller is to delete this mesh using decrRef() as it is
3739 * \throw If the coordinates array is not set.
3740 * \throw If the nodal connectivity of cells is not defined.
3741 * \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3742 * \throw If magnitude of \a vec is less than 1e-6.
3743 * \throw If the plane does not intersect any 2D cell of \a this mesh.
3744 * \throw If \a this includes quadratic cells.
3746 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3748 checkFullyDefined();
3749 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3750 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3751 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3752 if(candidates->empty())
3753 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3754 std::vector<int> nodes;
3755 DataArrayInt *cellIds1D=0;
3756 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3757 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3758 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3759 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3760 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3761 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3762 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3763 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3764 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3766 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3767 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3769 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3770 int ncellsSub=subMesh->getNumberOfCells();
3771 std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3772 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3773 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3774 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3775 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3777 const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3778 const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3779 for(int i=0;i<ncellsSub;i++)
3781 if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3783 if(cut3DSurf[i].first!=-2)
3785 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3786 connI->pushBackSilent(conn->getNumberOfTuples());
3787 cellIds2->pushBackSilent(i);
3791 int cellId3DSurf=cut3DSurf[i].second;
3792 int offset=nodalI[cellId3DSurf]+1;
3793 int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3794 for(int j=0;j<nbOfEdges;j++)
3796 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3797 connI->pushBackSilent(conn->getNumberOfTuples());
3798 cellIds2->pushBackSilent(cellId3DSurf);
3803 if(cellIds2->empty())
3804 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3805 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3806 ret->setCoords(mDesc1->getCoords());
3807 ret->setConnectivity(conn,connI,true);
3808 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3813 * Finds cells whose bounding boxes intersect a given plane.
3814 * \param [in] origin - 3 components of a point defining location of the plane.
3815 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3816 * must be greater than 1e-6.
3817 * \param [in] eps - half-thickness of the plane.
3818 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3819 * cells. The caller is to delete this array using decrRef() as it is no more
3821 * \throw If the coordinates array is not set.
3822 * \throw If the nodal connectivity of cells is not defined.
3823 * \throw If \a this->getSpaceDimension() != 3.
3824 * \throw If magnitude of \a vec is less than 1e-6.
3825 * \sa buildSlice3D()
3827 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3829 checkFullyDefined();
3830 if(getSpaceDimension()!=3)
3831 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3832 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3834 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3836 vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3837 double angle=acos(vec[2]/normm);
3838 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3842 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3843 MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3844 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3846 mw->getBoundingBox(bbox);
3847 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3848 cellIds=mw->getCellsInBoundingBox(bbox,eps);
3852 getBoundingBox(bbox);
3853 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3854 cellIds=getCellsInBoundingBox(bbox,eps);
3856 return cellIds.retn();
3860 * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3861 * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3862 * No consideration of coordinate is done by this method.
3863 * 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)
3864 * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3866 bool MEDCouplingUMesh::isContiguous1D() const
3868 if(getMeshDimension()!=1)
3869 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3870 int nbCells=getNumberOfCells();
3872 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3873 const int *connI=_nodal_connec_index->getConstPointer();
3874 const int *conn=_nodal_connec->getConstPointer();
3875 int ref=conn[connI[0]+2];
3876 for(int i=1;i<nbCells;i++)
3878 if(conn[connI[i]+1]!=ref)
3880 ref=conn[connI[i]+2];
3886 * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3887 * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3888 * \param pt reference point of the line
3889 * \param v normalized director vector of the line
3890 * \param eps max precision before throwing an exception
3891 * \param res output of size this->getNumberOfCells
3893 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3895 if(getMeshDimension()!=1)
3896 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3897 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3898 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3899 if(getSpaceDimension()!=3)
3900 throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3901 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3902 const double *fPtr=f->getArray()->getConstPointer();
3904 for(int i=0;i<getNumberOfCells();i++)
3906 const double *tmp1=fPtr+3*i;
3907 tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3908 tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3909 tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3910 double n1=INTERP_KERNEL::norm<3>(tmp);
3911 n1/=INTERP_KERNEL::norm<3>(tmp1);
3913 throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3915 const double *coo=getCoords()->getConstPointer();
3916 for(int i=0;i<getNumberOfNodes();i++)
3918 std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3919 std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3920 res[i]=std::accumulate(tmp,tmp+3,0.);
3925 * 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.
3926 * \a this is expected to be a mesh so that its space dimension is equal to its
3927 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3928 * 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).
3930 * 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
3931 * 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).
3932 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3934 * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3935 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3937 * \param [in] ptBg the start pointer (included) of the coordinates of the point
3938 * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3939 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3940 * \return the positive value of the distance.
3941 * \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
3943 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3945 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
3947 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3948 if(meshDim!=spaceDim-1)
3949 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3950 if(meshDim!=2 && meshDim!=1)
3951 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3952 checkFullyDefined();
3953 if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3954 { 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()); }
3955 DataArrayInt *ret1=0;
3956 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
3957 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
3958 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
3959 cellId=*ret1Safe->begin();
3960 return *ret0->begin();
3964 * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
3965 * to \a this and the first \a cellId in \a this corresponding to the returned distance.
3966 * 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
3967 * 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).
3968 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3970 * \a this is expected to be a mesh so that its space dimension is equal to its
3971 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3972 * 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).
3974 * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
3975 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3977 * \param [in] pts the list of points in which each tuple represents a point
3978 * \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.
3979 * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
3980 * \throw if number of components of \a pts is not equal to the space dimension.
3981 * \throw if mesh dimension of \a this is not equal to space dimension - 1.
3982 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
3984 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
3987 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
3988 pts->checkAllocated();
3989 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3990 if(meshDim!=spaceDim-1)
3991 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
3992 if(meshDim!=2 && meshDim!=1)
3993 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
3994 if(pts->getNumberOfComponents()!=spaceDim)
3996 std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
3997 throw INTERP_KERNEL::Exception(oss.str().c_str());
3999 checkFullyDefined();
4000 int nbCells=getNumberOfCells();
4002 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4003 int nbOfPts=pts->getNumberOfTuples();
4004 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4005 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4006 const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4007 double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4008 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4009 const double *bbox(bboxArr->begin());
4014 BBTreeDst<3> myTree(bbox,0,0,nbCells);
4015 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4017 double x=std::numeric_limits<double>::max();
4018 std::vector<int> elems;
4019 myTree.getMinDistanceOfMax(ptsPtr,x);
4020 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4021 DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4027 BBTreeDst<2> myTree(bbox,0,0,nbCells);
4028 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4030 double x=std::numeric_limits<double>::max();
4031 std::vector<int> elems;
4032 myTree.getMinDistanceOfMax(ptsPtr,x);
4033 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4034 DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4039 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4041 cellIds=ret1.retn();
4046 * \param [in] pt the start pointer (included) of the coordinates of the point
4047 * \param [in] cellIdsBg the start pointer (included) of cellIds
4048 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4049 * \param [in] nc nodal connectivity
4050 * \param [in] ncI nodal connectivity index
4051 * \param [in,out] ret0 the min distance between \a this and the external input point
4052 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4053 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4055 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)
4058 ret0=std::numeric_limits<double>::max();
4059 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4061 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4063 case INTERP_KERNEL::NORM_TRI3:
4065 double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4067 { ret0=tmp; cellId=*zeCell; }
4070 case INTERP_KERNEL::NORM_QUAD4:
4071 case INTERP_KERNEL::NORM_POLYGON:
4073 double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4075 { ret0=tmp; cellId=*zeCell; }
4079 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4085 * \param [in] pt the start pointer (included) of the coordinates of the point
4086 * \param [in] cellIdsBg the start pointer (included) of cellIds
4087 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4088 * \param [in] nc nodal connectivity
4089 * \param [in] ncI nodal connectivity index
4090 * \param [in,out] ret0 the min distance between \a this and the external input point
4091 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4092 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4094 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)
4097 ret0=std::numeric_limits<double>::max();
4098 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4100 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4102 case INTERP_KERNEL::NORM_SEG2:
4104 std::size_t uselessEntry=0;
4105 double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4108 { ret0=tmp; cellId=*zeCell; }
4112 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4118 * Finds cells in contact with a ball (i.e. a point with precision).
4119 * 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.
4120 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4122 * \warning This method is suitable if the caller intends to evaluate only one
4123 * point, for more points getCellsContainingPoints() is recommended as it is
4125 * \param [in] pos - array of coordinates of the ball central point.
4126 * \param [in] eps - ball radius.
4127 * \return int - a smallest id of cells being in contact with the ball, -1 in case
4128 * if there are no such cells.
4129 * \throw If the coordinates array is not set.
4130 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4132 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4134 std::vector<int> elts;
4135 getCellsContainingPoint(pos,eps,elts);
4138 return elts.front();
4142 * Finds cells in contact with a ball (i.e. a point with precision).
4143 * 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.
4144 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4145 * \warning This method is suitable if the caller intends to evaluate only one
4146 * point, for more points getCellsContainingPoints() is recommended as it is
4148 * \param [in] pos - array of coordinates of the ball central point.
4149 * \param [in] eps - ball radius.
4150 * \param [out] elts - vector returning ids of the found cells. It is cleared
4151 * before inserting ids.
4152 * \throw If the coordinates array is not set.
4153 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4155 * \if ENABLE_EXAMPLES
4156 * \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4157 * \ref py_mcumesh_getCellsContainingPoint "Here is a Python example".
4160 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4162 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4163 getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4164 elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4169 namespace ParaMEDMEM
4171 template<const int SPACEDIMM>
4175 static const int MY_SPACEDIM=SPACEDIMM;
4176 static const int MY_MESHDIM=8;
4177 typedef int MyConnType;
4178 static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4180 // useless, but for windows compilation ...
4181 const double* getCoordinatesPtr() const { return 0; }
4182 const int* getConnectivityPtr() const { return 0; }
4183 const int* getConnectivityIndexPtr() const { return 0; }
4184 INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4191 * Warning the nodes in \a m should be decrRefed ! To avoid that Node * pointer be replaced by another instance.
4193 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m)
4195 INTERP_KERNEL::Edge *ret(0);
4196 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]));
4197 m[n0]=bg[0]; m[n1]=bg[1];
4200 case INTERP_KERNEL::NORM_SEG2:
4202 ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4205 case INTERP_KERNEL::NORM_SEG3:
4207 INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4208 INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4209 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4210 // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4211 bool colinearity(inters.areColinears());
4212 delete e1; delete e2;
4214 { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4216 { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4220 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4225 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4227 INTERP_KERNEL::Edge *ret=0;
4230 case INTERP_KERNEL::NORM_SEG2:
4232 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4235 case INTERP_KERNEL::NORM_SEG3:
4237 INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4238 INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4239 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4240 // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4241 bool colinearity=inters.areColinears();
4242 delete e1; delete e2;
4244 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4246 ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4247 mapp2[bg[2]].second=false;
4251 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4257 * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4258 * the global mesh 'mDesc'.
4259 * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4260 * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4262 INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4263 std::map<INTERP_KERNEL::Node *,int>& mapp)
4266 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.
4267 const double *coo=mDesc->getCoords()->getConstPointer();
4268 const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4269 const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4271 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4272 s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4273 for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4275 INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4276 mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4278 INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4279 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4281 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4282 ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4284 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4286 if((*it2).second.second)
4287 mapp[(*it2).second.first]=(*it2).first;
4288 ((*it2).second.first)->decrRef();
4293 INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4297 int locId=nodeId-offset2;
4298 return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4302 int locId=nodeId-offset1;
4303 return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4305 return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4309 * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4311 void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4312 const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4313 /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4315 for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4317 int eltId1=abs(*desc1)-1;
4318 for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4320 std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4321 if(it==mappRev.end())
4323 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4334 template<int SPACEDIM>
4335 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4336 double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4338 elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4339 int *eltsIndexPtr(eltsIndex->getPointer());
4340 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4341 const double *bbox(bboxArr->begin());
4342 int nbOfCells=getNumberOfCells();
4343 const int *conn=_nodal_connec->getConstPointer();
4344 const int *connI=_nodal_connec_index->getConstPointer();
4345 double bb[2*SPACEDIM];
4346 BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4347 for(int i=0;i<nbOfPoints;i++)
4349 eltsIndexPtr[i+1]=eltsIndexPtr[i];
4350 for(int j=0;j<SPACEDIM;j++)
4352 bb[2*j]=pos[SPACEDIM*i+j];
4353 bb[2*j+1]=pos[SPACEDIM*i+j];
4355 std::vector<int> candidates;
4356 myTree.getIntersectingElems(bb,candidates);
4357 for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4359 int sz(connI[(*iter)+1]-connI[*iter]-1);
4360 INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4362 if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4363 status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4367 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4368 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4369 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4370 std::vector<INTERP_KERNEL::Node *> nodes(sz);
4371 INTERP_KERNEL::QuadraticPolygon *pol(0);
4372 for(int j=0;j<sz;j++)
4374 int nodeId(conn[connI[*iter]+1+j]);
4375 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4377 if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4378 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4380 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4381 INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4382 double a(0.),b(0.),c(0.);
4383 a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4384 status=pol->isInOrOut2(n);
4385 delete pol; n->decrRef();
4389 eltsIndexPtr[i+1]++;
4390 elts->pushBackSilent(*iter);
4396 * Finds cells in contact with several balls (i.e. points with precision).
4397 * This method is an extension of getCellContainingPoint() and
4398 * getCellsContainingPoint() for the case of multiple points.
4399 * 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.
4400 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4401 * \param [in] pos - an array of coordinates of points in full interlace mode :
4402 * X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4403 * this->getSpaceDimension() * \a nbOfPoints
4404 * \param [in] nbOfPoints - number of points to locate within \a this mesh.
4405 * \param [in] eps - radius of balls (i.e. the precision).
4406 * \param [out] elts - vector returning ids of found cells.
4407 * \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4408 * dividing cell ids in \a elts into groups each referring to one
4409 * point. Its every element (except the last one) is an index pointing to the
4410 * first id of a group of cells. For example cells in contact with the *i*-th
4411 * point are described by following range of indices:
4412 * [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4413 * \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4414 * Number of cells in contact with the *i*-th point is
4415 * \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4416 * \throw If the coordinates array is not set.
4417 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4419 * \if ENABLE_EXAMPLES
4420 * \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4421 * \ref py_mcumesh_getCellsContainingPoints "Here is a Python example".
4424 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4425 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4427 int spaceDim=getSpaceDimension();
4428 int mDim=getMeshDimension();
4433 const double *coords=_coords->getConstPointer();
4434 getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4441 throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4443 else if(spaceDim==2)
4447 const double *coords=_coords->getConstPointer();
4448 getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4451 throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4453 else if(spaceDim==1)
4457 const double *coords=_coords->getConstPointer();
4458 getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4461 throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4464 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4468 * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4469 * least two its edges intersect each other anywhere except their extremities. An
4470 * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4471 * \param [in,out] cells - a vector returning ids of the found cells. It is not
4472 * cleared before filling in.
4473 * \param [in] eps - precision.
4474 * \throw If \a this->getMeshDimension() != 2.
4475 * \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4477 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4479 const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4480 if(getMeshDimension()!=2)
4481 throw INTERP_KERNEL::Exception(msg);
4482 int spaceDim=getSpaceDimension();
4483 if(spaceDim!=2 && spaceDim!=3)
4484 throw INTERP_KERNEL::Exception(msg);
4485 const int *conn=_nodal_connec->getConstPointer();
4486 const int *connI=_nodal_connec_index->getConstPointer();
4487 int nbOfCells=getNumberOfCells();
4488 std::vector<double> cell2DinS2;
4489 for(int i=0;i<nbOfCells;i++)
4491 int offset=connI[i];
4492 int nbOfNodesForCell=connI[i+1]-offset-1;
4493 if(nbOfNodesForCell<=3)
4495 bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4496 project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4497 if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4504 * This method is typically requested to unbutterfly 2D linear cells in \b this.
4506 * 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.
4507 * 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.
4509 * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4510 * This convex envelop is computed using Jarvis march algorithm.
4511 * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4512 * 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)
4513 * 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.
4515 * \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.
4516 * \sa MEDCouplingUMesh::colinearize2D
4518 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4520 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4521 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D works only for meshDim=2 and spaceDim=2 !");
4522 checkFullyDefined();
4523 const double *coords=getCoords()->getConstPointer();
4524 int nbOfCells=getNumberOfCells();
4525 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4526 nodalConnecIndexOut->alloc(nbOfCells+1,1);
4527 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4528 int *workIndexOut=nodalConnecIndexOut->getPointer();
4530 const int *nodalConnecIn=_nodal_connec->getConstPointer();
4531 const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4532 std::set<INTERP_KERNEL::NormalizedCellType> types;
4533 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4534 isChanged->alloc(0,1);
4535 for(int i=0;i<nbOfCells;i++,workIndexOut++)
4537 int pos=nodalConnecOut->getNumberOfTuples();
4538 if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4539 isChanged->pushBackSilent(i);
4540 types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4541 workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4543 if(isChanged->empty())
4545 setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4547 return isChanged.retn();
4551 * This method is \b NOT const because it can modify \a this.
4552 * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4553 * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4554 * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4555 * \b 1 for translation and rotation around point of 'mesh1D'.
4556 * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.
4558 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4560 checkFullyDefined();
4561 mesh1D->checkFullyDefined();
4562 if(!mesh1D->isContiguous1D())
4563 throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4564 if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4565 throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4566 if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4567 throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4568 if(mesh1D->getMeshDimension()!=1)
4569 throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4571 if(isPresenceOfQuadratic())
4573 if(mesh1D->isFullyQuadratic())
4576 throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4579 int oldNbOfNodes=getNumberOfNodes();
4580 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4585 newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4590 newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4594 throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4596 setCoords(newCoords);
4597 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4603 * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4604 * If it is not the case an exception will be thrown.
4605 * This method is non const because the coordinate of \a this can be appended with some new points issued from
4606 * intersection of plane defined by ('origin','vec').
4607 * This method has one in/out parameter : 'cut3DCurve'.
4608 * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4609 * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4610 * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4611 * This method will throw an exception if \a this contains a non linear segment.
4613 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4615 checkFullyDefined();
4616 if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4617 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4618 int ncells=getNumberOfCells();
4619 int nnodes=getNumberOfNodes();
4620 double vec2[3],vec3[3],vec4[3];
4621 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4623 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4624 vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4625 const int *conn=_nodal_connec->getConstPointer();
4626 const int *connI=_nodal_connec_index->getConstPointer();
4627 const double *coo=_coords->getConstPointer();
4628 std::vector<double> addCoo;
4629 for(int i=0;i<ncells;i++)
4631 if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4633 if(cut3DCurve[i]==-2)
4635 int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4636 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];
4637 double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4638 double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4639 if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4641 const double *st2=coo+3*st;
4642 vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4643 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]));
4644 if(pos>eps && pos<1-eps)
4646 int nNode=((int)addCoo.size())/3;
4647 vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4648 addCoo.insert(addCoo.end(),vec4,vec4+3);
4649 cut3DCurve[i]=nnodes+nNode;
4655 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4659 int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4660 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4661 coo2->alloc(newNbOfNodes,3);
4662 double *tmp=coo2->getPointer();
4663 tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4664 std::copy(addCoo.begin(),addCoo.end(),tmp);
4665 DataArrayDouble::SetArrayIn(coo2,_coords);
4670 * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4671 * \param mesh1D is the input 1D mesh used for translation computation.
4672 * \return newCoords new coords filled by this method.
4674 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4676 int oldNbOfNodes=getNumberOfNodes();
4677 int nbOf1DCells=mesh1D->getNumberOfCells();
4678 int spaceDim=getSpaceDimension();
4679 DataArrayDouble *ret=DataArrayDouble::New();
4680 std::vector<bool> isQuads;
4681 int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4682 ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4683 double *retPtr=ret->getPointer();
4684 const double *coords=getCoords()->getConstPointer();
4685 double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4687 std::vector<double> c;
4691 for(int i=0;i<nbOf1DCells;i++)
4694 mesh1D->getNodeIdsOfCell(i,v);
4696 mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4697 mesh1D->getCoordinatesOfNode(v[0],c);
4698 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4699 for(int j=0;j<oldNbOfNodes;j++)
4700 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4704 mesh1D->getCoordinatesOfNode(v[1],c);
4705 mesh1D->getCoordinatesOfNode(v[0],c);
4706 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4707 for(int j=0;j<oldNbOfNodes;j++)
4708 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4711 ret->copyStringInfoFrom(*getCoords());
4716 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4717 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4718 * \return newCoords new coords filled by this method.
4720 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4722 if(mesh1D->getSpaceDimension()==2)
4723 return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4724 if(mesh1D->getSpaceDimension()==3)
4725 return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4726 throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4730 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4731 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4732 * \return newCoords new coords filled by this method.
4734 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4737 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4738 int oldNbOfNodes=getNumberOfNodes();
4739 int nbOf1DCells=mesh1D->getNumberOfCells();
4741 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4742 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4743 int nbOfLevsInVec=nbOf1DCells+1;
4744 ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4745 double *retPtr=ret->getPointer();
4746 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4747 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4748 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4749 tmp->setCoords(tmp2);
4750 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4751 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4752 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4753 for(int i=1;i<nbOfLevsInVec;i++)
4755 const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4756 const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4757 const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4758 const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4759 tmp->translate(vec);
4760 double tmp3[2],radius,alpha,alpha0;
4761 const double *p0=i+1<nbOfLevsInVec?begin:third;
4762 const double *p1=i+1<nbOfLevsInVec?end:begin;
4763 const double *p2=i+1<nbOfLevsInVec?third:end;
4764 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4765 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]);
4766 double angle=acos(cosangle/(radius*radius));
4767 tmp->rotate(end,0,angle);
4768 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4774 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4775 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4776 * \return newCoords new coords filled by this method.
4778 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4781 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4782 int oldNbOfNodes=getNumberOfNodes();
4783 int nbOf1DCells=mesh1D->getNumberOfCells();
4785 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4786 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4787 int nbOfLevsInVec=nbOf1DCells+1;
4788 ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4789 double *retPtr=ret->getPointer();
4790 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4791 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4792 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4793 tmp->setCoords(tmp2);
4794 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4795 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4796 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4797 for(int i=1;i<nbOfLevsInVec;i++)
4799 const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4800 const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4801 const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4802 const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4803 tmp->translate(vec);
4804 double tmp3[2],radius,alpha,alpha0;
4805 const double *p0=i+1<nbOfLevsInVec?begin:third;
4806 const double *p1=i+1<nbOfLevsInVec?end:begin;
4807 const double *p2=i+1<nbOfLevsInVec?third:end;
4808 double vecPlane[3]={
4809 (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4810 (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4811 (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4813 double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4816 vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4817 double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4818 double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4820 double c2=cos(asin(s2));
4822 {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4823 {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4824 {-vec2[1]*s2, vec2[0]*s2, c2}
4826 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]};
4827 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]};
4828 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]};
4829 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4830 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]);
4831 double angle=acos(cosangle/(radius*radius));
4832 tmp->rotate(end,vecPlane,angle);
4834 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4840 * This method is private because not easy to use for end user. This method is const contrary to
4841 * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4842 * the coords sorted slice by slice.
4843 * \param isQuad specifies presence of quadratic cells.
4845 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4847 int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4848 int nbOf2DCells=getNumberOfCells();
4849 int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4850 MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4851 const int *conn=_nodal_connec->getConstPointer();
4852 const int *connI=_nodal_connec_index->getConstPointer();
4853 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4854 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4855 newConnI->alloc(nbOf3DCells+1,1);
4856 int *newConnIPtr=newConnI->getPointer();
4858 std::vector<int> newc;
4859 for(int j=0;j<nbOf2DCells;j++)
4861 AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4862 *newConnIPtr++=(int)newc.size();
4864 newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4865 int *newConnPtr=newConn->getPointer();
4866 int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4867 newConnIPtr=newConnI->getPointer();
4868 for(int iz=0;iz<nbOf1DCells;iz++)
4871 std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4872 for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4874 int icell=(int)(iter-newc.begin());
4875 if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4878 *newConnPtr=(*iter)+iz*deltaPerLev;
4883 *newConnPtr=(*iter);
4886 ret->setConnectivity(newConn,newConnI,true);
4887 ret->setCoords(getCoords());
4892 * Checks if \a this mesh is constituted by only quadratic cells.
4893 * \return bool - \c true if there are only quadratic cells in \a this mesh.
4894 * \throw If the coordinates array is not set.
4895 * \throw If the nodal connectivity of cells is not defined.
4897 bool MEDCouplingUMesh::isFullyQuadratic() const
4899 checkFullyDefined();
4901 int nbOfCells=getNumberOfCells();
4902 for(int i=0;i<nbOfCells && ret;i++)
4904 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4905 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4906 ret=cm.isQuadratic();
4912 * Checks if \a this mesh includes any quadratic cell.
4913 * \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4914 * \throw If the coordinates array is not set.
4915 * \throw If the nodal connectivity of cells is not defined.
4917 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4919 checkFullyDefined();
4921 int nbOfCells=getNumberOfCells();
4922 for(int i=0;i<nbOfCells && !ret;i++)
4924 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4925 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4926 ret=cm.isQuadratic();
4932 * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4933 * this mesh, it remains unchanged.
4934 * \throw If the coordinates array is not set.
4935 * \throw If the nodal connectivity of cells is not defined.
4937 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4939 checkFullyDefined();
4940 int nbOfCells=getNumberOfCells();
4942 const int *iciptr=_nodal_connec_index->getConstPointer();
4943 for(int i=0;i<nbOfCells;i++)
4945 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4946 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4947 if(cm.isQuadratic())
4949 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4950 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4951 if(!cml.isDynamic())
4952 delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4954 delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4959 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4960 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4961 const int *icptr=_nodal_connec->getConstPointer();
4962 newConn->alloc(getMeshLength()-delta,1);
4963 newConnI->alloc(nbOfCells+1,1);
4964 int *ocptr=newConn->getPointer();
4965 int *ociptr=newConnI->getPointer();
4968 for(int i=0;i<nbOfCells;i++,ociptr++)
4970 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4971 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4972 if(!cm.isQuadratic())
4974 _types.insert(type);
4975 ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4976 ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4980 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4981 _types.insert(typel);
4982 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4983 int newNbOfNodes=cml.getNumberOfNodes();
4985 newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4986 *ocptr++=(int)typel;
4987 ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4988 ociptr[1]=ociptr[0]+newNbOfNodes+1;
4991 setConnectivity(newConn,newConnI,false);
4995 * This method converts all linear cell in \a this to quadratic one.
4996 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4997 * 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)
4998 * 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.
4999 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5000 * end of the existing coordinates.
5002 * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5003 * corresponding quadratic cells. 1 is those creating the 'most' complex.
5004 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5006 * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5008 * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5010 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5012 DataArrayInt *conn=0,*connI=0;
5013 DataArrayDouble *coords=0;
5014 std::set<INTERP_KERNEL::NormalizedCellType> types;
5015 checkFullyDefined();
5016 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5017 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5018 int meshDim=getMeshDimension();
5019 switch(conversionType)
5025 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5026 connSafe=conn; connISafe=connI; coordsSafe=coords;
5029 ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5030 connSafe=conn; connISafe=connI; coordsSafe=coords;
5033 ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5034 connSafe=conn; connISafe=connI; coordsSafe=coords;
5037 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5045 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5046 connSafe=conn; connISafe=connI; coordsSafe=coords;
5049 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5050 connSafe=conn; connISafe=connI; coordsSafe=coords;
5053 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5054 connSafe=conn; connISafe=connI; coordsSafe=coords;
5057 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5062 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5064 setConnectivity(connSafe,connISafe,false);
5066 setCoords(coordsSafe);
5072 * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
5073 * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
5074 * The nodes to be added in those 2D cells are defined by the pair of \a nodeIdsToAdd and \a nodeIdsIndexToAdd.
5075 * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
5076 * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
5077 * This method can be seen as the opposite method of colinearize2D.
5078 * 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
5079 * to avoid to modify the numbering of existing nodes.
5081 * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
5082 * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
5083 * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
5084 * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
5085 * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
5086 * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
5087 * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
5089 * \sa buildDescendingConnectivity2
5091 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
5092 const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
5094 if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
5095 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
5096 nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
5097 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
5098 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
5099 if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
5100 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
5101 //DataArrayInt *out0(0),*outi0(0);
5102 //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
5103 //MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s(out0),outi0s(outi0);
5104 //out0s=out0s->buildUnique(); out0s->sort(true);
5109 * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5110 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5111 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5113 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5115 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5116 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5117 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5118 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5119 int nbOfCells=getNumberOfCells();
5120 int nbOfNodes=getNumberOfNodes();
5121 const int *cPtr=_nodal_connec->getConstPointer();
5122 const int *icPtr=_nodal_connec_index->getConstPointer();
5123 int lastVal=0,offset=nbOfNodes;
5124 for(int i=0;i<nbOfCells;i++,icPtr++)
5126 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5127 if(type==INTERP_KERNEL::NORM_SEG2)
5129 types.insert(INTERP_KERNEL::NORM_SEG3);
5130 newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5131 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5132 newConn->pushBackSilent(offset++);
5134 newConnI->pushBackSilent(lastVal);
5135 ret->pushBackSilent(i);
5140 lastVal+=(icPtr[1]-icPtr[0]);
5141 newConnI->pushBackSilent(lastVal);
5142 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5145 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5146 coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5150 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
5152 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5153 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5154 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5156 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5157 DataArrayInt *conn1D=0,*conn1DI=0;
5158 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5159 DataArrayDouble *coordsTmp=0;
5160 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5161 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5162 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5163 const int *c1DPtr=conn1D->begin();
5164 const int *c1DIPtr=conn1DI->begin();
5165 int nbOfCells=getNumberOfCells();
5166 const int *cPtr=_nodal_connec->getConstPointer();
5167 const int *icPtr=_nodal_connec_index->getConstPointer();
5169 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5171 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5172 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5173 if(!cm.isQuadratic())
5175 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5176 types.insert(typ2); newConn->pushBackSilent(typ2);
5177 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5178 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5179 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5180 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5181 newConnI->pushBackSilent(lastVal);
5182 ret->pushBackSilent(i);
5187 lastVal+=(icPtr[1]-icPtr[0]);
5188 newConnI->pushBackSilent(lastVal);
5189 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5192 conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5197 * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5198 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5199 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5201 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5203 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5204 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5205 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5208 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5210 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5211 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5213 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5214 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5215 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5217 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5218 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5219 DataArrayInt *conn1D=0,*conn1DI=0;
5220 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5221 DataArrayDouble *coordsTmp=0;
5222 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5223 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5224 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5225 const int *c1DPtr=conn1D->begin();
5226 const int *c1DIPtr=conn1DI->begin();
5227 int nbOfCells=getNumberOfCells();
5228 const int *cPtr=_nodal_connec->getConstPointer();
5229 const int *icPtr=_nodal_connec_index->getConstPointer();
5230 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5231 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5233 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5234 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5235 if(!cm.isQuadratic())
5237 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5238 types.insert(typ2); newConn->pushBackSilent(typ2);
5239 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5240 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5241 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5242 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5243 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5244 newConnI->pushBackSilent(lastVal);
5245 ret->pushBackSilent(i);
5250 lastVal+=(icPtr[1]-icPtr[0]);
5251 newConnI->pushBackSilent(lastVal);
5252 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5255 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5256 coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5261 * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5262 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5263 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5265 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5267 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5268 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5269 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5272 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5274 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5275 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5276 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5277 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5279 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5280 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5281 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5283 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5284 const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5285 DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5286 std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5287 DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5288 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5289 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5290 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5291 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5292 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5293 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5294 const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5295 int nbOfCells=getNumberOfCells();
5296 const int *cPtr=_nodal_connec->getConstPointer();
5297 const int *icPtr=_nodal_connec_index->getConstPointer();
5298 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5299 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5301 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5302 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5303 if(!cm.isQuadratic())
5305 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5306 if(typ2==INTERP_KERNEL::NORM_ERROR)
5308 std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5309 throw INTERP_KERNEL::Exception(oss.str().c_str());
5311 types.insert(typ2); newConn->pushBackSilent(typ2);
5312 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5313 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5314 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5315 for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5317 int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5318 int tmpPos=newConn->getNumberOfTuples();
5319 newConn->pushBackSilent(nodeId2);
5320 ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5322 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5323 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5324 newConnI->pushBackSilent(lastVal);
5325 ret->pushBackSilent(i);
5330 lastVal+=(icPtr[1]-icPtr[0]);
5331 newConnI->pushBackSilent(lastVal);
5332 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5335 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5336 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5337 coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5338 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5339 std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5340 int *c=newConn->getPointer();
5341 const int *cI(newConnI->begin());
5342 for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5343 c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5344 offset=coordsTmp2Safe->getNumberOfTuples();
5345 for(const int *elt=ret->begin();elt!=ret->end();elt++)
5346 c[cI[(*elt)+1]-1]+=offset;
5347 coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5352 * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5353 * so that the number of cells remains the same. Quadratic faces are converted to
5354 * polygons. This method works only for 2D meshes in
5355 * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5356 * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5357 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5358 * \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5359 * a polylinized edge constituting the input polygon.
5360 * \throw If the coordinates array is not set.
5361 * \throw If the nodal connectivity of cells is not defined.
5362 * \throw If \a this->getMeshDimension() != 2.
5363 * \throw If \a this->getSpaceDimension() != 2.
5365 void MEDCouplingUMesh::tessellate2D(double eps)
5367 checkFullyDefined();
5368 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
5369 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5370 double epsa=fabs(eps);
5371 if(epsa<std::numeric_limits<double>::min())
5372 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 !");
5373 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5374 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5375 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5376 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5377 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5378 revDesc1=0; revDescIndx1=0;
5379 mDesc->tessellate2DCurve(eps);
5380 subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5381 setCoords(mDesc->getCoords());
5385 * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5386 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5387 * \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5388 * a sub-divided edge.
5389 * \throw If the coordinates array is not set.
5390 * \throw If the nodal connectivity of cells is not defined.
5391 * \throw If \a this->getMeshDimension() != 1.
5392 * \throw If \a this->getSpaceDimension() != 2.
5394 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5396 checkFullyDefined();
5397 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5398 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5399 double epsa=fabs(eps);
5400 if(epsa<std::numeric_limits<double>::min())
5401 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve : epsilon is null ! Please specify a higher epsilon. If too tiny it can lead to a huge amount of nodes and memory !");
5402 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5403 int nbCells=getNumberOfCells();
5404 int nbNodes=getNumberOfNodes();
5405 const int *conn=_nodal_connec->getConstPointer();
5406 const int *connI=_nodal_connec_index->getConstPointer();
5407 const double *coords=_coords->getConstPointer();
5408 std::vector<double> addCoo;
5409 std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5410 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5411 newConnI->alloc(nbCells+1,1);
5412 int *newConnIPtr=newConnI->getPointer();
5415 INTERP_KERNEL::Node *tmp2[3];
5416 std::set<INTERP_KERNEL::NormalizedCellType> types;
5417 for(int i=0;i<nbCells;i++,newConnIPtr++)
5419 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5420 if(cm.isQuadratic())
5421 {//assert(connI[i+1]-connI[i]-1==3)
5422 tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5423 tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5424 tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5425 tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5426 INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5429 eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5430 types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5432 newConnIPtr[1]=(int)newConn.size();
5436 types.insert(INTERP_KERNEL::NORM_SEG2);
5437 newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5438 newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5439 newConnIPtr[1]=newConnIPtr[0]+3;
5444 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5445 newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5446 newConnIPtr[1]=newConnIPtr[0]+3;
5449 if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5452 DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5453 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5454 newConnArr->alloc((int)newConn.size(),1);
5455 std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5456 DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5457 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5458 newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5459 double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5460 std::copy(addCoo.begin(),addCoo.end(),work);
5461 DataArrayDouble::SetArrayIn(newCoords,_coords);
5466 * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5467 * In addition, returns an array mapping new cells to old ones. <br>
5468 * This method typically increases the number of cells in \a this mesh
5469 * but the number of nodes remains \b unchanged.
5470 * That's why the 3D splitting policies
5471 * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5472 * \param [in] policy - specifies a pattern used for splitting.
5473 * The semantic of \a policy is:
5474 * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5475 * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5476 * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8 into 5 TETRA4 (for 3D mesh only).
5477 * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8 into 6 TETRA4 (for 3D mesh only).
5478 * \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5479 * an id of old cell producing it. The caller is to delete this array using
5480 * decrRef() as it is no more needed.
5481 * \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5482 * \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5483 * and \a this->getMeshDimension() != 3.
5484 * \throw If \a policy is not one of the four discussed above.
5485 * \throw If the nodal connectivity of cells is not defined.
5486 * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5488 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5493 return simplexizePol0();
5495 return simplexizePol1();
5496 case (int) INTERP_KERNEL::PLANAR_FACE_5:
5497 return simplexizePlanarFace5();
5498 case (int) INTERP_KERNEL::PLANAR_FACE_6:
5499 return simplexizePlanarFace6();
5501 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)");
5506 * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5507 * - 1D: INTERP_KERNEL::NORM_SEG2
5508 * - 2D: INTERP_KERNEL::NORM_TRI3
5509 * - 3D: INTERP_KERNEL::NORM_TETRA4.
5511 * This method is useful for users that need to use P1 field services as
5512 * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5513 * All these methods need mesh support containing only simplex cells.
5514 * \return bool - \c true if there are only simplex cells in \a this mesh.
5515 * \throw If the coordinates array is not set.
5516 * \throw If the nodal connectivity of cells is not defined.
5517 * \throw If \a this->getMeshDimension() < 1.
5519 bool MEDCouplingUMesh::areOnlySimplexCells() const
5521 checkFullyDefined();
5522 int mdim=getMeshDimension();
5523 if(mdim<1 || mdim>3)
5524 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5525 int nbCells=getNumberOfCells();
5526 const int *conn=_nodal_connec->getConstPointer();
5527 const int *connI=_nodal_connec_index->getConstPointer();
5528 for(int i=0;i<nbCells;i++)
5530 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5538 * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5540 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5542 checkConnectivityFullyDefined();
5543 if(getMeshDimension()!=2)
5544 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5545 int nbOfCells=getNumberOfCells();
5546 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5547 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5548 ret->alloc(nbOfCells+nbOfCutCells,1);
5549 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5550 int *retPt=ret->getPointer();
5551 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5552 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5553 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5554 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5555 int *pt=newConn->getPointer();
5556 int *ptI=newConnI->getPointer();
5558 const int *oldc=_nodal_connec->getConstPointer();
5559 const int *ci=_nodal_connec_index->getConstPointer();
5560 for(int i=0;i<nbOfCells;i++,ci++)
5562 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5564 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5565 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5566 pt=std::copy(tmp,tmp+8,pt);
5575 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5576 ptI[1]=ptI[0]+ci[1]-ci[0];
5581 _nodal_connec->decrRef();
5582 _nodal_connec=newConn.retn();
5583 _nodal_connec_index->decrRef();
5584 _nodal_connec_index=newConnI.retn();
5591 * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5593 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5595 checkConnectivityFullyDefined();
5596 if(getMeshDimension()!=2)
5597 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5598 int nbOfCells=getNumberOfCells();
5599 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5600 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5601 ret->alloc(nbOfCells+nbOfCutCells,1);
5602 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5603 int *retPt=ret->getPointer();
5604 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5605 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5606 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5607 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5608 int *pt=newConn->getPointer();
5609 int *ptI=newConnI->getPointer();
5611 const int *oldc=_nodal_connec->getConstPointer();
5612 const int *ci=_nodal_connec_index->getConstPointer();
5613 for(int i=0;i<nbOfCells;i++,ci++)
5615 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5617 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5618 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5619 pt=std::copy(tmp,tmp+8,pt);
5628 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5629 ptI[1]=ptI[0]+ci[1]-ci[0];
5634 _nodal_connec->decrRef();
5635 _nodal_connec=newConn.retn();
5636 _nodal_connec_index->decrRef();
5637 _nodal_connec_index=newConnI.retn();
5644 * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5646 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5648 checkConnectivityFullyDefined();
5649 if(getMeshDimension()!=3)
5650 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5651 int nbOfCells=getNumberOfCells();
5652 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5653 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5654 ret->alloc(nbOfCells+4*nbOfCutCells,1);
5655 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5656 int *retPt=ret->getPointer();
5657 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5658 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5659 newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5660 newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5661 int *pt=newConn->getPointer();
5662 int *ptI=newConnI->getPointer();
5664 const int *oldc=_nodal_connec->getConstPointer();
5665 const int *ci=_nodal_connec_index->getConstPointer();
5666 for(int i=0;i<nbOfCells;i++,ci++)
5668 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5670 for(int j=0;j<5;j++,pt+=5,ptI++)
5672 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5673 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];
5680 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5681 ptI[1]=ptI[0]+ci[1]-ci[0];
5686 _nodal_connec->decrRef();
5687 _nodal_connec=newConn.retn();
5688 _nodal_connec_index->decrRef();
5689 _nodal_connec_index=newConnI.retn();
5696 * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5698 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5700 checkConnectivityFullyDefined();
5701 if(getMeshDimension()!=3)
5702 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5703 int nbOfCells=getNumberOfCells();
5704 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5705 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5706 ret->alloc(nbOfCells+5*nbOfCutCells,1);
5707 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5708 int *retPt=ret->getPointer();
5709 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5710 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5711 newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5712 newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5713 int *pt=newConn->getPointer();
5714 int *ptI=newConnI->getPointer();
5716 const int *oldc=_nodal_connec->getConstPointer();
5717 const int *ci=_nodal_connec_index->getConstPointer();
5718 for(int i=0;i<nbOfCells;i++,ci++)
5720 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5722 for(int j=0;j<6;j++,pt+=5,ptI++)
5724 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5725 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];
5732 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5733 ptI[1]=ptI[0]+ci[1]-ci[0];
5738 _nodal_connec->decrRef();
5739 _nodal_connec=newConn.retn();
5740 _nodal_connec_index->decrRef();
5741 _nodal_connec_index=newConnI.retn();
5748 * 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.
5749 * This method completly ignore coordinates.
5750 * \param nodeSubdived is the nodal connectivity of subdivision of edges
5751 * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5752 * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5753 * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5755 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5757 checkFullyDefined();
5758 if(getMeshDimension()!=2)
5759 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5760 int nbOfCells=getNumberOfCells();
5761 int *connI=_nodal_connec_index->getPointer();
5763 for(int i=0;i<nbOfCells;i++,connI++)
5765 int offset=descIndex[i];
5766 int nbOfEdges=descIndex[i+1]-offset;
5768 bool ddirect=desc[offset+nbOfEdges-1]>0;
5769 int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5770 int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5771 for(int j=0;j<nbOfEdges;j++)
5773 bool direct=desc[offset+j]>0;
5774 int edgeId=std::abs(desc[offset+j])-1;
5775 if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5777 int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5778 int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5779 int ref2=direct?id1:id2;
5782 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5783 newConnLgth+=nbOfSubNodes-1;
5788 std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5789 throw INTERP_KERNEL::Exception(oss.str().c_str());
5794 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5797 newConnLgth++;//+1 is for cell type
5798 connI[1]=newConnLgth;
5801 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5802 newConn->alloc(newConnLgth,1);
5803 int *work=newConn->getPointer();
5804 for(int i=0;i<nbOfCells;i++)
5806 *work++=INTERP_KERNEL::NORM_POLYGON;
5807 int offset=descIndex[i];
5808 int nbOfEdges=descIndex[i+1]-offset;
5809 for(int j=0;j<nbOfEdges;j++)
5811 bool direct=desc[offset+j]>0;
5812 int edgeId=std::abs(desc[offset+j])-1;
5814 work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5817 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5818 std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5819 work=std::copy(it,it+nbOfSubNodes-1,work);
5823 DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5826 _types.insert(INTERP_KERNEL::NORM_POLYGON);
5830 * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5831 * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5832 * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5833 * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5834 * so it can be useful to call mergeNodes() before calling this method.
5835 * \throw If \a this->getMeshDimension() <= 1.
5836 * \throw If the coordinates array is not set.
5837 * \throw If the nodal connectivity of cells is not defined.
5839 void MEDCouplingUMesh::convertDegeneratedCells()
5841 checkFullyDefined();
5842 if(getMeshDimension()<=1)
5843 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5844 int nbOfCells=getNumberOfCells();
5847 int initMeshLgth=getMeshLength();
5848 int *conn=_nodal_connec->getPointer();
5849 int *index=_nodal_connec_index->getPointer();
5853 for(int i=0;i<nbOfCells;i++)
5855 lgthOfCurCell=index[i+1]-posOfCurCell;
5856 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5858 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5859 conn+newPos+1,newLgth);
5860 conn[newPos]=newType;
5862 posOfCurCell=index[i+1];
5865 if(newPos!=initMeshLgth)
5866 _nodal_connec->reAlloc(newPos);
5871 * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5872 * A cell is considered to be oriented correctly if an angle between its
5873 * normal vector and a given vector is less than \c PI / \c 2.
5874 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5876 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5878 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5879 * is not cleared before filling in.
5880 * \throw If \a this->getMeshDimension() != 2.
5881 * \throw If \a this->getSpaceDimension() != 3.
5883 * \if ENABLE_EXAMPLES
5884 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5885 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5888 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
5890 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5891 throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5892 int nbOfCells=getNumberOfCells();
5893 const int *conn=_nodal_connec->getConstPointer();
5894 const int *connI=_nodal_connec_index->getConstPointer();
5895 const double *coordsPtr=_coords->getConstPointer();
5896 for(int i=0;i<nbOfCells;i++)
5898 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5899 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5901 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5902 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5909 * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5910 * considered to be oriented correctly if an angle between its normal vector and a
5911 * given vector is less than \c PI / \c 2.
5912 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5914 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5916 * \throw If \a this->getMeshDimension() != 2.
5917 * \throw If \a this->getSpaceDimension() != 3.
5919 * \if ENABLE_EXAMPLES
5920 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5921 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5924 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
5926 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5927 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5928 int nbOfCells=getNumberOfCells();
5929 int *conn=_nodal_connec->getPointer();
5930 const int *connI=_nodal_connec_index->getConstPointer();
5931 const double *coordsPtr=_coords->getConstPointer();
5932 bool isModified=false;
5933 for(int i=0;i<nbOfCells;i++)
5935 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5936 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5938 bool isQuadratic(INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic());
5939 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5944 std::vector<int> tmp(connI[i+1]-connI[i]-2);
5945 std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5946 std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5950 int sz(((int)(connI[i+1]-connI[i]-1))/2);
5951 std::vector<int> tmp0(sz-1),tmp1(sz);
5952 std::copy(conn+connI[i]+2,conn+connI[i]+1+sz,tmp0.rbegin());
5953 std::copy(conn+connI[i]+1+sz,conn+connI[i+1],tmp1.rbegin());
5954 std::copy(tmp0.begin(),tmp0.end(),conn+connI[i]+2);
5955 std::copy(tmp1.begin(),tmp1.end(),conn+connI[i]+1+sz);
5961 _nodal_connec->declareAsNew();
5966 * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5967 * oriented facets. The normal vector of the facet should point out of the cell.
5968 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5969 * is not cleared before filling in.
5970 * \throw If \a this->getMeshDimension() != 3.
5971 * \throw If \a this->getSpaceDimension() != 3.
5972 * \throw If the coordinates array is not set.
5973 * \throw If the nodal connectivity of cells is not defined.
5975 * \if ENABLE_EXAMPLES
5976 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5977 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5980 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
5982 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5983 throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5984 int nbOfCells=getNumberOfCells();
5985 const int *conn=_nodal_connec->getConstPointer();
5986 const int *connI=_nodal_connec_index->getConstPointer();
5987 const double *coordsPtr=_coords->getConstPointer();
5988 for(int i=0;i<nbOfCells;i++)
5990 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5991 if(type==INTERP_KERNEL::NORM_POLYHED)
5993 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6000 * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6002 * \throw If \a this->getMeshDimension() != 3.
6003 * \throw If \a this->getSpaceDimension() != 3.
6004 * \throw If the coordinates array is not set.
6005 * \throw If the nodal connectivity of cells is not defined.
6006 * \throw If the reparation fails.
6008 * \if ENABLE_EXAMPLES
6009 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6010 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6012 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6014 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
6016 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6017 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6018 int nbOfCells=getNumberOfCells();
6019 int *conn=_nodal_connec->getPointer();
6020 const int *connI=_nodal_connec_index->getConstPointer();
6021 const double *coordsPtr=_coords->getConstPointer();
6022 for(int i=0;i<nbOfCells;i++)
6024 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6025 if(type==INTERP_KERNEL::NORM_POLYHED)
6029 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6030 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6032 catch(INTERP_KERNEL::Exception& e)
6034 std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6035 throw INTERP_KERNEL::Exception(oss.str().c_str());
6043 * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6044 * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6045 * according to which the first facet of the cell should be oriented to have the normal vector
6046 * pointing out of cell.
6047 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6048 * cells. The caller is to delete this array using decrRef() as it is no more
6050 * \throw If \a this->getMeshDimension() != 3.
6051 * \throw If \a this->getSpaceDimension() != 3.
6052 * \throw If the coordinates array is not set.
6053 * \throw If the nodal connectivity of cells is not defined.
6055 * \if ENABLE_EXAMPLES
6056 * \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6057 * \ref py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6059 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6061 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6063 const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6064 if(getMeshDimension()!=3)
6065 throw INTERP_KERNEL::Exception(msg);
6066 int spaceDim=getSpaceDimension();
6068 throw INTERP_KERNEL::Exception(msg);
6070 int nbOfCells=getNumberOfCells();
6071 int *conn=_nodal_connec->getPointer();
6072 const int *connI=_nodal_connec_index->getConstPointer();
6073 const double *coo=getCoords()->getConstPointer();
6074 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6075 for(int i=0;i<nbOfCells;i++)
6077 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6078 if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6080 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6082 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6083 cells->pushBackSilent(i);
6087 return cells.retn();
6091 * This method is a faster method to correct orientation of all 3D cells in \a this.
6092 * 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.
6093 * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6095 * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6096 * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons,
6098 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6100 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6101 throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6102 int nbOfCells=getNumberOfCells();
6103 int *conn=_nodal_connec->getPointer();
6104 const int *connI=_nodal_connec_index->getConstPointer();
6105 const double *coordsPtr=_coords->getConstPointer();
6106 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6107 for(int i=0;i<nbOfCells;i++)
6109 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6112 case INTERP_KERNEL::NORM_TETRA4:
6114 if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6116 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6117 ret->pushBackSilent(i);
6121 case INTERP_KERNEL::NORM_PYRA5:
6123 if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6125 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6126 ret->pushBackSilent(i);
6130 case INTERP_KERNEL::NORM_PENTA6:
6131 case INTERP_KERNEL::NORM_HEXA8:
6132 case INTERP_KERNEL::NORM_HEXGP12:
6134 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6136 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6137 ret->pushBackSilent(i);
6141 case INTERP_KERNEL::NORM_POLYHED:
6143 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6145 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6146 ret->pushBackSilent(i);
6151 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 !");
6159 * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6160 * If it is not the case an exception will be thrown.
6161 * This method is fast because the first cell of \a this is used to compute the plane.
6162 * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6163 * \param pos output of size at least 3 used to store a point owned of searched plane.
6165 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6167 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6168 throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6169 const int *conn=_nodal_connec->getConstPointer();
6170 const int *connI=_nodal_connec_index->getConstPointer();
6171 const double *coordsPtr=_coords->getConstPointer();
6172 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6173 std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6177 * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6178 * cells. Currently cells of the following types are treated:
6179 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6180 * For a cell of other type an exception is thrown.
6181 * Space dimension of a 2D mesh can be either 2 or 3.
6182 * The Edge Ratio of a cell \f$t\f$ is:
6183 * \f$\frac{|t|_\infty}{|t|_0}\f$,
6184 * where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6185 * the smallest edge lengths of \f$t\f$.
6186 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6187 * cells and one time, lying on \a this mesh. The caller is to delete this
6188 * field using decrRef() as it is no more needed.
6189 * \throw If the coordinates array is not set.
6190 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6191 * \throw If the connectivity data array has more than one component.
6192 * \throw If the connectivity data array has a named component.
6193 * \throw If the connectivity index data array has more than one component.
6194 * \throw If the connectivity index data array has a named component.
6195 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6196 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6197 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6199 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6202 int spaceDim=getSpaceDimension();
6203 int meshDim=getMeshDimension();
6204 if(spaceDim!=2 && spaceDim!=3)
6205 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6206 if(meshDim!=2 && meshDim!=3)
6207 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6208 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6210 int nbOfCells=getNumberOfCells();
6211 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6212 arr->alloc(nbOfCells,1);
6213 double *pt=arr->getPointer();
6214 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6215 const int *conn=_nodal_connec->getConstPointer();
6216 const int *connI=_nodal_connec_index->getConstPointer();
6217 const double *coo=_coords->getConstPointer();
6219 for(int i=0;i<nbOfCells;i++,pt++)
6221 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6224 case INTERP_KERNEL::NORM_TRI3:
6226 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6227 *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6230 case INTERP_KERNEL::NORM_QUAD4:
6232 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6233 *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6236 case INTERP_KERNEL::NORM_TETRA4:
6238 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6239 *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6243 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6245 conn+=connI[i+1]-connI[i];
6247 ret->setName("EdgeRatio");
6248 ret->synchronizeTimeWithSupport();
6253 * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6254 * cells. Currently cells of the following types are treated:
6255 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6256 * For a cell of other type an exception is thrown.
6257 * Space dimension of a 2D mesh can be either 2 or 3.
6258 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6259 * cells and one time, lying on \a this mesh. The caller is to delete this
6260 * field using decrRef() as it is no more needed.
6261 * \throw If the coordinates array is not set.
6262 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6263 * \throw If the connectivity data array has more than one component.
6264 * \throw If the connectivity data array has a named component.
6265 * \throw If the connectivity index data array has more than one component.
6266 * \throw If the connectivity index data array has a named component.
6267 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6268 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6269 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6271 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6274 int spaceDim=getSpaceDimension();
6275 int meshDim=getMeshDimension();
6276 if(spaceDim!=2 && spaceDim!=3)
6277 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6278 if(meshDim!=2 && meshDim!=3)
6279 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6280 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6282 int nbOfCells=getNumberOfCells();
6283 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6284 arr->alloc(nbOfCells,1);
6285 double *pt=arr->getPointer();
6286 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6287 const int *conn=_nodal_connec->getConstPointer();
6288 const int *connI=_nodal_connec_index->getConstPointer();
6289 const double *coo=_coords->getConstPointer();
6291 for(int i=0;i<nbOfCells;i++,pt++)
6293 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6296 case INTERP_KERNEL::NORM_TRI3:
6298 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6299 *pt=INTERP_KERNEL::triAspectRatio(tmp);
6302 case INTERP_KERNEL::NORM_QUAD4:
6304 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6305 *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6308 case INTERP_KERNEL::NORM_TETRA4:
6310 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6311 *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6315 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6317 conn+=connI[i+1]-connI[i];
6319 ret->setName("AspectRatio");
6320 ret->synchronizeTimeWithSupport();
6325 * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6326 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6327 * treated: INTERP_KERNEL::NORM_QUAD4.
6328 * For a cell of other type an exception is thrown.
6329 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6330 * cells and one time, lying on \a this mesh. The caller is to delete this
6331 * field using decrRef() as it is no more needed.
6332 * \throw If the coordinates array is not set.
6333 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6334 * \throw If the connectivity data array has more than one component.
6335 * \throw If the connectivity data array has a named component.
6336 * \throw If the connectivity index data array has more than one component.
6337 * \throw If the connectivity index data array has a named component.
6338 * \throw If \a this->getMeshDimension() != 2.
6339 * \throw If \a this->getSpaceDimension() != 3.
6340 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6342 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6345 int spaceDim=getSpaceDimension();
6346 int meshDim=getMeshDimension();
6348 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6350 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6351 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6353 int nbOfCells=getNumberOfCells();
6354 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6355 arr->alloc(nbOfCells,1);
6356 double *pt=arr->getPointer();
6357 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6358 const int *conn=_nodal_connec->getConstPointer();
6359 const int *connI=_nodal_connec_index->getConstPointer();
6360 const double *coo=_coords->getConstPointer();
6362 for(int i=0;i<nbOfCells;i++,pt++)
6364 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6367 case INTERP_KERNEL::NORM_QUAD4:
6369 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6370 *pt=INTERP_KERNEL::quadWarp(tmp);
6374 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6376 conn+=connI[i+1]-connI[i];
6378 ret->setName("Warp");
6379 ret->synchronizeTimeWithSupport();
6385 * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6386 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6387 * treated: INTERP_KERNEL::NORM_QUAD4.
6388 * For a cell of other type an exception is thrown.
6389 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6390 * cells and one time, lying on \a this mesh. The caller is to delete this
6391 * field using decrRef() as it is no more needed.
6392 * \throw If the coordinates array is not set.
6393 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6394 * \throw If the connectivity data array has more than one component.
6395 * \throw If the connectivity data array has a named component.
6396 * \throw If the connectivity index data array has more than one component.
6397 * \throw If the connectivity index data array has a named component.
6398 * \throw If \a this->getMeshDimension() != 2.
6399 * \throw If \a this->getSpaceDimension() != 3.
6400 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6402 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6405 int spaceDim=getSpaceDimension();
6406 int meshDim=getMeshDimension();
6408 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6410 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6411 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6413 int nbOfCells=getNumberOfCells();
6414 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6415 arr->alloc(nbOfCells,1);
6416 double *pt=arr->getPointer();
6417 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6418 const int *conn=_nodal_connec->getConstPointer();
6419 const int *connI=_nodal_connec_index->getConstPointer();
6420 const double *coo=_coords->getConstPointer();
6422 for(int i=0;i<nbOfCells;i++,pt++)
6424 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6427 case INTERP_KERNEL::NORM_QUAD4:
6429 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6430 *pt=INTERP_KERNEL::quadSkew(tmp);
6434 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6436 conn+=connI[i+1]-connI[i];
6438 ret->setName("Skew");
6439 ret->synchronizeTimeWithSupport();
6444 * This method aggregate the bbox of each cell and put it into bbox parameter.
6446 * \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)
6447 * For all other cases this input parameter is ignored.
6448 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6450 * \throw If \a this is not fully set (coordinates and connectivity).
6451 * \throw If a cell in \a this has no valid nodeId.
6452 * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6454 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6456 int mDim(getMeshDimension()),sDim(getSpaceDimension());
6457 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.
6458 return getBoundingBoxForBBTreeFast();
6459 if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6461 bool presenceOfQuadratic(false);
6462 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6464 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6465 if(cm.isQuadratic())
6466 presenceOfQuadratic=true;
6468 if(!presenceOfQuadratic)
6469 return getBoundingBoxForBBTreeFast();
6470 if(mDim==2 && sDim==2)
6471 return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6473 return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6475 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) !");
6479 * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6480 * So meshes having quadratic cells the computed bounding boxes can be invalid !
6482 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6484 * \throw If \a this is not fully set (coordinates and connectivity).
6485 * \throw If a cell in \a this has no valid nodeId.
6487 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6489 checkFullyDefined();
6490 int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6491 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6492 double *bbox(ret->getPointer());
6493 for(int i=0;i<nbOfCells*spaceDim;i++)
6495 bbox[2*i]=std::numeric_limits<double>::max();
6496 bbox[2*i+1]=-std::numeric_limits<double>::max();
6498 const double *coordsPtr(_coords->getConstPointer());
6499 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6500 for(int i=0;i<nbOfCells;i++)
6502 int offset=connI[i]+1;
6503 int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6504 for(int j=0;j<nbOfNodesForCell;j++)
6506 int nodeId=conn[offset+j];
6507 if(nodeId>=0 && nodeId<nbOfNodes)
6509 for(int k=0;k<spaceDim;k++)
6511 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6512 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6519 std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6520 throw INTERP_KERNEL::Exception(oss.str().c_str());
6527 * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6528 * useful for 2D meshes having quadratic cells
6529 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6530 * the two extremities of the arc of circle).
6532 * \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)
6533 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6534 * \throw If \a this is not fully defined.
6535 * \throw If \a this is not a mesh with meshDimension equal to 2.
6536 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6537 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6539 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6541 checkFullyDefined();
6542 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6543 if(spaceDim!=2 || mDim!=2)
6544 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!");
6545 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6546 double *bbox(ret->getPointer());
6547 const double *coords(_coords->getConstPointer());
6548 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6549 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6551 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6552 int sz(connI[1]-connI[0]-1);
6553 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6554 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6555 INTERP_KERNEL::QuadraticPolygon *pol(0);
6556 for(int j=0;j<sz;j++)
6558 int nodeId(conn[*connI+1+j]);
6559 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6561 if(!cm.isQuadratic())
6562 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6564 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6565 INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6566 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax();
6572 * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6573 * useful for 2D meshes having quadratic cells
6574 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6575 * the two extremities of the arc of circle).
6577 * \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)
6578 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6579 * \throw If \a this is not fully defined.
6580 * \throw If \a this is not a mesh with meshDimension equal to 1.
6581 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6582 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6584 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6586 checkFullyDefined();
6587 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6588 if(spaceDim!=2 || mDim!=1)
6589 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!");
6590 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6591 double *bbox(ret->getPointer());
6592 const double *coords(_coords->getConstPointer());
6593 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6594 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6596 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6597 int sz(connI[1]-connI[0]-1);
6598 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6599 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6600 INTERP_KERNEL::Edge *edge(0);
6601 for(int j=0;j<sz;j++)
6603 int nodeId(conn[*connI+1+j]);
6604 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6606 if(!cm.isQuadratic())
6607 edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6609 edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6610 const INTERP_KERNEL::Bounds& b(edge->getBounds());
6611 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6618 namespace ParaMEDMEMImpl
6623 ConnReader(const int *c, int val):_conn(c),_val(val) { }
6624 bool operator() (const int& pos) { return _conn[pos]!=_val; }
6633 ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6634 bool operator() (const int& pos) { return _conn[pos]==_val; }
6644 * This method expects that \a this is sorted by types. If not an exception will be thrown.
6645 * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6646 * \a this is composed in cell types.
6647 * The returned array is of size 3*n where n is the number of different types present in \a this.
6648 * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here.
6649 * This parameter is kept only for compatibility with other methode listed above.
6651 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6653 checkConnectivityFullyDefined();
6654 const int *conn=_nodal_connec->getConstPointer();
6655 const int *connI=_nodal_connec_index->getConstPointer();
6656 const int *work=connI;
6657 int nbOfCells=getNumberOfCells();
6658 std::size_t n=getAllGeoTypes().size();
6659 std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6660 std::set<INTERP_KERNEL::NormalizedCellType> types;
6661 for(std::size_t i=0;work!=connI+nbOfCells;i++)
6663 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6664 if(types.find(typ)!=types.end())
6666 std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6667 oss << " is not contiguous !";
6668 throw INTERP_KERNEL::Exception(oss.str().c_str());
6672 const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6673 ret[3*i+1]=(int)std::distance(work,work2);
6680 * This method is used to check that this has contiguous cell type in same order than described in \a code.
6681 * only for types cell, type node is not managed.
6682 * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6683 * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6684 * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6685 * If 2 or more same geometric type is in \a code and exception is thrown too.
6687 * This method firstly checks
6688 * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6689 * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6690 * an exception is thrown too.
6692 * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6693 * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown
6694 * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6696 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6699 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6700 std::size_t sz=code.size();
6703 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6704 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6706 bool isNoPflUsed=true;
6707 for(std::size_t i=0;i<n;i++)
6708 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6710 types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6712 if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6713 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6714 isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6717 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6720 if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6721 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6722 if(types.size()==_types.size())
6725 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6727 int *retPtr=ret->getPointer();
6728 const int *connI=_nodal_connec_index->getConstPointer();
6729 const int *conn=_nodal_connec->getConstPointer();
6730 int nbOfCells=getNumberOfCells();
6733 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6735 i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6736 int offset=(int)std::distance(connI,i);
6737 const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6738 int nbOfCellsOfCurType=(int)std::distance(i,j);
6739 if(code[3*kk+2]==-1)
6740 for(int k=0;k<nbOfCellsOfCurType;k++)
6744 int idInIdsPerType=code[3*kk+2];
6745 if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6747 const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6750 zePfl->checkAllocated();
6751 if(zePfl->getNumberOfComponents()==1)
6753 for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6755 if(*k>=0 && *k<nbOfCellsOfCurType)
6756 *retPtr=(*k)+offset;
6759 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6760 oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6761 throw INTERP_KERNEL::Exception(oss.str().c_str());
6766 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6769 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6773 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6774 oss << " should be in [0," << idsPerType.size() << ") !";
6775 throw INTERP_KERNEL::Exception(oss.str().c_str());
6784 * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6785 * 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.
6786 * 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.
6787 * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6789 * \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.
6790 * \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,
6791 * \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6792 * \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.
6793 * This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6794 * \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
6796 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6799 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6800 if(profile->getNumberOfComponents()!=1)
6801 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6802 checkConnectivityFullyDefined();
6803 const int *conn=_nodal_connec->getConstPointer();
6804 const int *connI=_nodal_connec_index->getConstPointer();
6805 int nbOfCells=getNumberOfCells();
6806 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6807 std::vector<int> typeRangeVals(1);
6808 for(const int *i=connI;i!=connI+nbOfCells;)
6810 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6811 if(std::find(types.begin(),types.end(),curType)!=types.end())
6813 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6815 types.push_back(curType);
6816 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6817 typeRangeVals.push_back((int)std::distance(connI,i));
6820 DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6821 profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6822 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6823 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6824 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6826 int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6827 code.resize(3*nbOfCastsFinal);
6828 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6829 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6830 for(int i=0;i<nbOfCastsFinal;i++)
6832 int castId=castsPresent->getIJ(i,0);
6833 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6834 idsInPflPerType2.push_back(tmp3);
6835 code[3*i]=(int)types[castId];
6836 code[3*i+1]=tmp3->getNumberOfTuples();
6837 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6838 if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6840 tmp4->copyStringInfoFrom(*profile);
6841 idsPerType2.push_back(tmp4);
6842 code[3*i+2]=(int)idsPerType2.size()-1;
6849 std::size_t sz2=idsInPflPerType2.size();
6850 idsInPflPerType.resize(sz2);
6851 for(std::size_t i=0;i<sz2;i++)
6853 DataArrayInt *locDa=idsInPflPerType2[i];
6855 idsInPflPerType[i]=locDa;
6857 std::size_t sz=idsPerType2.size();
6858 idsPerType.resize(sz);
6859 for(std::size_t i=0;i<sz;i++)
6861 DataArrayInt *locDa=idsPerType2[i];
6863 idsPerType[i]=locDa;
6868 * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6869 * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6870 * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6871 * 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.
6873 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
6875 checkFullyDefined();
6876 nM1LevMesh->checkFullyDefined();
6877 if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6878 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6879 if(_coords!=nM1LevMesh->getCoords())
6880 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6881 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6882 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6883 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6884 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6885 desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6886 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6887 tmp->setConnectivity(tmp0,tmp1);
6888 tmp->renumberCells(ret0->getConstPointer(),false);
6889 revDesc=tmp->getNodalConnectivity();
6890 revDescIndx=tmp->getNodalConnectivityIndex();
6891 DataArrayInt *ret=0;
6892 if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6895 ret->getMaxValue(tmp2);
6897 std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6898 throw INTERP_KERNEL::Exception(oss.str().c_str());
6903 revDescIndx->incrRef();
6906 meshnM1Old2New=ret0;
6911 * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6912 * necessary for writing the mesh to MED file. Additionally returns a permutation array
6913 * in "Old to New" mode.
6914 * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6915 * this array using decrRef() as it is no more needed.
6916 * \throw If the nodal connectivity of cells is not defined.
6918 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
6920 checkConnectivityFullyDefined();
6921 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6922 renumberCells(ret->getConstPointer(),false);
6927 * This methods checks that cells are sorted by their types.
6928 * This method makes asumption (no check) that connectivity is correctly set before calling.
6930 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6932 checkFullyDefined();
6933 const int *conn=_nodal_connec->getConstPointer();
6934 const int *connI=_nodal_connec_index->getConstPointer();
6935 int nbOfCells=getNumberOfCells();
6936 std::set<INTERP_KERNEL::NormalizedCellType> types;
6937 for(const int *i=connI;i!=connI+nbOfCells;)
6939 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6940 if(types.find(curType)!=types.end())
6942 types.insert(curType);
6943 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6949 * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6950 * The geometric type order is specified by MED file.
6952 * \sa MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6954 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
6956 return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6960 * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6961 * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
6962 * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6963 * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6965 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6967 checkFullyDefined();
6968 const int *conn=_nodal_connec->getConstPointer();
6969 const int *connI=_nodal_connec_index->getConstPointer();
6970 int nbOfCells=getNumberOfCells();
6974 std::set<INTERP_KERNEL::NormalizedCellType> sg;
6975 for(const int *i=connI;i!=connI+nbOfCells;)
6977 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6978 const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6979 if(isTypeExists!=orderEnd)
6981 int pos=(int)std::distance(orderBg,isTypeExists);
6985 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6989 if(sg.find(curType)==sg.end())
6991 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7002 * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
7003 * 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
7004 * 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'.
7006 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
7008 checkConnectivityFullyDefined();
7009 int nbOfCells=getNumberOfCells();
7010 const int *conn=_nodal_connec->getConstPointer();
7011 const int *connI=_nodal_connec_index->getConstPointer();
7012 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
7013 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
7014 tmpa->alloc(nbOfCells,1);
7015 tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
7016 tmpb->fillWithZero();
7017 int *tmp=tmpa->getPointer();
7018 int *tmp2=tmpb->getPointer();
7019 for(const int *i=connI;i!=connI+nbOfCells;i++)
7021 const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
7024 int pos=(int)std::distance(orderBg,where);
7026 tmp[std::distance(connI,i)]=pos;
7030 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
7031 std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
7032 oss << " has a type " << cm.getRepr() << " not in input array of type !";
7033 throw INTERP_KERNEL::Exception(oss.str().c_str());
7036 nbPerType=tmpb.retn();
7041 * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7043 * \return a new object containing the old to new correspondance.
7045 * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7047 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7049 return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7053 * 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.
7054 * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7055 * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7056 * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7058 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7060 DataArrayInt *nbPerType=0;
7061 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7062 nbPerType->decrRef();
7063 return tmpa->buildPermArrPerLevel();
7067 * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7068 * The number of cells remains unchanged after the call of this method.
7069 * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7070 * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7072 * \return the array giving the correspondance old to new.
7074 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7076 checkFullyDefined();
7078 const int *conn=_nodal_connec->getConstPointer();
7079 const int *connI=_nodal_connec_index->getConstPointer();
7080 int nbOfCells=getNumberOfCells();
7081 std::vector<INTERP_KERNEL::NormalizedCellType> types;
7082 for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7083 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7085 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7086 types.push_back(curType);
7087 for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7089 DataArrayInt *ret=DataArrayInt::New();
7090 ret->alloc(nbOfCells,1);
7091 int *retPtr=ret->getPointer();
7092 std::fill(retPtr,retPtr+nbOfCells,-1);
7094 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7096 for(const int *i=connI;i!=connI+nbOfCells;i++)
7097 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7098 retPtr[std::distance(connI,i)]=newCellId++;
7100 renumberCells(retPtr,false);
7105 * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7106 * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7107 * This method makes asumption that connectivity is correctly set before calling.
7109 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7111 checkConnectivityFullyDefined();
7112 const int *conn=_nodal_connec->getConstPointer();
7113 const int *connI=_nodal_connec_index->getConstPointer();
7114 int nbOfCells=getNumberOfCells();
7115 std::vector<MEDCouplingUMesh *> ret;
7116 for(const int *i=connI;i!=connI+nbOfCells;)
7118 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7119 int beginCellId=(int)std::distance(connI,i);
7120 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7121 int endCellId=(int)std::distance(connI,i);
7122 int sz=endCellId-beginCellId;
7123 int *cells=new int[sz];
7124 for(int j=0;j<sz;j++)
7125 cells[j]=beginCellId+j;
7126 MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7134 * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7135 * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7136 * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7138 * \return a newly allocated instance, that the caller must manage.
7139 * \throw If \a this contains more than one geometric type.
7140 * \throw If the nodal connectivity of \a this is not fully defined.
7141 * \throw If the internal data is not coherent.
7143 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7145 checkConnectivityFullyDefined();
7146 if(_types.size()!=1)
7147 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7148 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7149 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7150 ret->setCoords(getCoords());
7151 MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7154 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7155 retC->setNodalConnectivity(c);
7159 MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7161 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7162 DataArrayInt *c=0,*ci=0;
7163 convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7164 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7165 retD->setNodalConnectivity(cs,cis);
7170 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7172 checkConnectivityFullyDefined();
7173 if(_types.size()!=1)
7174 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7175 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7176 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7179 std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7180 oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7181 throw INTERP_KERNEL::Exception(oss.str().c_str());
7183 int nbCells=getNumberOfCells();
7185 int nbNodesPerCell=(int)cm.getNumberOfNodes();
7186 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7187 int *outPtr=connOut->getPointer();
7188 const int *conn=_nodal_connec->begin();
7189 const int *connI=_nodal_connec_index->begin();
7191 for(int i=0;i<nbCells;i++,connI++)
7193 if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7194 outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7197 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 << ") !";
7198 throw INTERP_KERNEL::Exception(oss.str().c_str());
7201 return connOut.retn();
7204 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7206 static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7207 checkConnectivityFullyDefined();
7208 if(_types.size()!=1)
7209 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7210 int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7212 throw INTERP_KERNEL::Exception(msg0);
7213 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7214 c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7215 int *cp(c->getPointer()),*cip(ci->getPointer());
7216 const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7218 for(int i=0;i<nbCells;i++,cip++,incip++)
7220 int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7221 int delta(stop-strt);
7224 if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7225 cp=std::copy(incp+strt,incp+stop,cp);
7227 throw INTERP_KERNEL::Exception(msg0);
7230 throw INTERP_KERNEL::Exception(msg0);
7231 cip[1]=cip[0]+delta;
7233 nodalConn=c.retn(); nodalConnIndex=ci.retn();
7237 * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7238 * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7239 * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7240 * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7241 * are not used here to avoid the build of big permutation array.
7243 * \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
7244 * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7245 * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7246 * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7247 * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7248 * output array gives for each chunck of same type the corresponding mesh id in \b ms.
7249 * \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
7250 * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7252 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7253 DataArrayInt *&szOfCellGrpOfSameType,
7254 DataArrayInt *&idInMsOfCellGrpOfSameType)
7256 std::vector<const MEDCouplingUMesh *> ms2;
7257 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7260 (*it)->checkConnectivityFullyDefined();
7264 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7265 const DataArrayDouble *refCoo=ms2[0]->getCoords();
7266 int meshDim=ms2[0]->getMeshDimension();
7267 std::vector<const MEDCouplingUMesh *> m1ssm;
7268 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7270 std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7271 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7273 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7274 ret1->alloc(0,1); ret2->alloc(0,1);
7275 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7277 if(meshDim!=(*it)->getMeshDimension())
7278 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7279 if(refCoo!=(*it)->getCoords())
7280 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7281 std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7282 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7283 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7284 for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7286 MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7287 m1ssmSingleAuto.push_back(singleCell);
7288 m1ssmSingle.push_back(singleCell);
7289 ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7292 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7293 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7294 std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7295 for(std::size_t i=0;i<m1ssm.size();i++)
7296 m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7297 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7298 szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7299 idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7304 * This method returns a newly created DataArrayInt instance.
7305 * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7307 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7309 checkFullyDefined();
7310 const int *conn=_nodal_connec->getConstPointer();
7311 const int *connIndex=_nodal_connec_index->getConstPointer();
7312 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7313 for(const int *w=begin;w!=end;w++)
7314 if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7315 ret->pushBackSilent(*w);
7320 * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7321 * are in [0:getNumberOfCells())
7323 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7325 checkFullyDefined();
7326 const int *conn=_nodal_connec->getConstPointer();
7327 const int *connI=_nodal_connec_index->getConstPointer();
7328 int nbOfCells=getNumberOfCells();
7329 std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7330 int *tmp=new int[nbOfCells];
7331 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7334 for(const int *i=connI;i!=connI+nbOfCells;i++)
7335 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7336 tmp[std::distance(connI,i)]=j++;
7338 DataArrayInt *ret=DataArrayInt::New();
7339 ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7340 ret->copyStringInfoFrom(*da);
7341 int *retPtr=ret->getPointer();
7342 const int *daPtr=da->getConstPointer();
7343 int nbOfElems=da->getNbOfElems();
7344 for(int k=0;k<nbOfElems;k++)
7345 retPtr[k]=tmp[daPtr[k]];
7351 * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7352 * This method \b works \b for mesh sorted by type.
7353 * cells whose ids is in 'idsPerGeoType' array.
7354 * This method conserves coords and name of mesh.
7356 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7358 std::vector<int> code=getDistributionOfTypes();
7359 std::size_t nOfTypesInThis=code.size()/3;
7360 int sz=0,szOfType=0;
7361 for(std::size_t i=0;i<nOfTypesInThis;i++)
7366 szOfType=code[3*i+1];
7368 for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7369 if(*work<0 || *work>=szOfType)
7371 std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7372 oss << ". It should be in [0," << szOfType << ") !";
7373 throw INTERP_KERNEL::Exception(oss.str().c_str());
7375 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7376 int *idsPtr=idsTokeep->getPointer();
7378 for(std::size_t i=0;i<nOfTypesInThis;i++)
7381 for(int j=0;j<code[3*i+1];j++)
7384 idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7385 offset+=code[3*i+1];
7387 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7388 ret->copyTinyInfoFrom(this);
7393 * This method returns a vector of size 'this->getNumberOfCells()'.
7394 * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7396 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7398 int ncell=getNumberOfCells();
7399 std::vector<bool> ret(ncell);
7400 const int *cI=getNodalConnectivityIndex()->getConstPointer();
7401 const int *c=getNodalConnectivity()->getConstPointer();
7402 for(int i=0;i<ncell;i++)
7404 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7405 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7406 ret[i]=cm.isQuadratic();
7412 * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7414 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7416 if(other->getType()!=UNSTRUCTURED)
7417 throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7418 const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7419 return MergeUMeshes(this,otherC);
7423 * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7424 * computed by averaging coordinates of cell nodes, so this method is not a right
7425 * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7426 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7427 * this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7428 * components. The caller is to delete this array using decrRef() as it is
7430 * \throw If the coordinates array is not set.
7431 * \throw If the nodal connectivity of cells is not defined.
7432 * \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7434 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7436 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7437 int spaceDim=getSpaceDimension();
7438 int nbOfCells=getNumberOfCells();
7439 ret->alloc(nbOfCells,spaceDim);
7440 ret->copyStringInfoFrom(*getCoords());
7441 double *ptToFill=ret->getPointer();
7442 const int *nodal=_nodal_connec->getConstPointer();
7443 const int *nodalI=_nodal_connec_index->getConstPointer();
7444 const double *coor=_coords->getConstPointer();
7445 for(int i=0;i<nbOfCells;i++)
7447 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7448 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7455 * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7456 * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the
7458 * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned
7459 * DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7461 * \sa MEDCouplingUMesh::getBarycenterAndOwner
7462 * \throw If \a this is not fully defined (coordinates and connectivity)
7463 * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7465 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7467 checkFullyDefined();
7468 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7469 int spaceDim=getSpaceDimension();
7470 int nbOfCells=getNumberOfCells();
7471 int nbOfNodes=getNumberOfNodes();
7472 ret->alloc(nbOfCells,spaceDim);
7473 double *ptToFill=ret->getPointer();
7474 const int *nodal=_nodal_connec->getConstPointer();
7475 const int *nodalI=_nodal_connec_index->getConstPointer();
7476 const double *coor=_coords->getConstPointer();
7477 for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7479 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7480 std::fill(ptToFill,ptToFill+spaceDim,0.);
7481 if(type!=INTERP_KERNEL::NORM_POLYHED)
7483 for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7485 if(*conn>=0 && *conn<nbOfNodes)
7486 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7489 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," << nbOfNodes << ") !";
7490 throw INTERP_KERNEL::Exception(oss.str().c_str());
7493 int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7494 if(nbOfNodesInCell>0)
7495 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7498 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7499 throw INTERP_KERNEL::Exception(oss.str().c_str());
7504 std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7506 for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7508 if(*it>=0 && *it<nbOfNodes)
7509 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7512 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," << nbOfNodes << ") !";
7513 throw INTERP_KERNEL::Exception(oss.str().c_str());
7517 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7520 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7521 throw INTERP_KERNEL::Exception(oss.str().c_str());
7529 * Returns a new DataArrayDouble holding barycenters of specified cells. The
7530 * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7531 * are specified via an array of cell ids.
7532 * \warning Validity of the specified cell ids is not checked!
7533 * Valid range is [ 0, \a this->getNumberOfCells() ).
7534 * \param [in] begin - an array of cell ids of interest.
7535 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7536 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7537 * end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7538 * caller is to delete this array using decrRef() as it is no more needed.
7539 * \throw If the coordinates array is not set.
7540 * \throw If the nodal connectivity of cells is not defined.
7542 * \if ENABLE_EXAMPLES
7543 * \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7544 * \ref py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7547 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7549 DataArrayDouble *ret=DataArrayDouble::New();
7550 int spaceDim=getSpaceDimension();
7551 int nbOfTuple=(int)std::distance(begin,end);
7552 ret->alloc(nbOfTuple,spaceDim);
7553 double *ptToFill=ret->getPointer();
7554 double *tmp=new double[spaceDim];
7555 const int *nodal=_nodal_connec->getConstPointer();
7556 const int *nodalI=_nodal_connec_index->getConstPointer();
7557 const double *coor=_coords->getConstPointer();
7558 for(const int *w=begin;w!=end;w++)
7560 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7561 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7569 * 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".
7570 * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7571 * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7572 * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7573 * This method is useful to detect 2D cells in 3D space that are not coplanar.
7575 * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7576 * \throw If spaceDim!=3 or meshDim!=2.
7577 * \throw If connectivity of \a this is invalid.
7578 * \throw If connectivity of a cell in \a this points to an invalid node.
7580 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7582 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7583 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7584 if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7585 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7586 ret->alloc(nbOfCells,4);
7587 double *retPtr(ret->getPointer());
7588 const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7589 const double *coor(_coords->begin());
7590 for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7592 double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7593 if(nodalI[1]-nodalI[0]>=3)
7595 for(int j=0;j<3;j++)
7597 int nodeId(nodal[nodalI[0]+1+j]);
7598 if(nodeId>=0 && nodeId<nbOfNodes)
7599 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7602 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7603 throw INTERP_KERNEL::Exception(oss.str().c_str());
7609 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7610 throw INTERP_KERNEL::Exception(oss.str().c_str());
7612 INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7613 retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7619 * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7622 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7625 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7626 da->checkAllocated();
7627 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7629 int nbOfTuples=da->getNumberOfTuples();
7630 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7631 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7632 c->alloc(2*nbOfTuples,1);
7633 cI->alloc(nbOfTuples+1,1);
7634 int *cp=c->getPointer();
7635 int *cip=cI->getPointer();
7637 for(int i=0;i<nbOfTuples;i++)
7639 *cp++=INTERP_KERNEL::NORM_POINT1;
7643 ret->setConnectivity(c,cI,true);
7647 * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7648 * Cells and nodes of
7649 * the first mesh precede cells and nodes of the second mesh within the result mesh.
7650 * \param [in] mesh1 - the first mesh.
7651 * \param [in] mesh2 - the second mesh.
7652 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7653 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7654 * is no more needed.
7655 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7656 * \throw If the coordinates array is not set in none of the meshes.
7657 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7658 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7660 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7662 std::vector<const MEDCouplingUMesh *> tmp(2);
7663 tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7664 return MergeUMeshes(tmp);
7668 * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7669 * Cells and nodes of
7670 * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7671 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7672 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7673 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7674 * is no more needed.
7675 * \throw If \a a.size() == 0.
7676 * \throw If \a a[ *i* ] == NULL.
7677 * \throw If the coordinates array is not set in none of the meshes.
7678 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7679 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7681 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7683 std::size_t sz=a.size();
7685 return MergeUMeshesLL(a);
7686 for(std::size_t ii=0;ii<sz;ii++)
7689 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7690 throw INTERP_KERNEL::Exception(oss.str().c_str());
7692 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7693 std::vector< const MEDCouplingUMesh * > aa(sz);
7695 for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7697 const MEDCouplingUMesh *cur=a[i];
7698 const DataArrayDouble *coo=cur->getCoords();
7700 spaceDim=coo->getNumberOfComponents();
7703 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7704 for(std::size_t i=0;i<sz;i++)
7706 bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7709 return MergeUMeshesLL(aa);
7714 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7717 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7718 std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7719 int meshDim=(*it)->getMeshDimension();
7720 int nbOfCells=(*it)->getNumberOfCells();
7721 int meshLgth=(*it++)->getMeshLength();
7722 for(;it!=a.end();it++)
7724 if(meshDim!=(*it)->getMeshDimension())
7725 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7726 nbOfCells+=(*it)->getNumberOfCells();
7727 meshLgth+=(*it)->getMeshLength();
7729 std::vector<const MEDCouplingPointSet *> aps(a.size());
7730 std::copy(a.begin(),a.end(),aps.begin());
7731 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7732 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7733 ret->setCoords(pts);
7734 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7735 c->alloc(meshLgth,1);
7736 int *cPtr=c->getPointer();
7737 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7738 cI->alloc(nbOfCells+1,1);
7739 int *cIPtr=cI->getPointer();
7743 for(it=a.begin();it!=a.end();it++)
7745 int curNbOfCell=(*it)->getNumberOfCells();
7746 const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7747 const int *curC=(*it)->_nodal_connec->getConstPointer();
7748 cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7749 for(int j=0;j<curNbOfCell;j++)
7751 const int *src=curC+curCI[j];
7753 for(;src!=curC+curCI[j+1];src++,cPtr++)
7761 offset+=curCI[curNbOfCell];
7762 offset2+=(*it)->getNumberOfNodes();
7765 ret->setConnectivity(c,cI,true);
7772 * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7773 * dimension and sharing the node coordinates array.
7774 * All cells of the first mesh precede all cells of the second mesh
7775 * within the result mesh.
7776 * \param [in] mesh1 - the first mesh.
7777 * \param [in] mesh2 - the second mesh.
7778 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7779 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7780 * is no more needed.
7781 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7782 * \throw If the meshes do not share the node coordinates array.
7783 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7784 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7786 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7788 std::vector<const MEDCouplingUMesh *> tmp(2);
7789 tmp[0]=mesh1; tmp[1]=mesh2;
7790 return MergeUMeshesOnSameCoords(tmp);
7794 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7795 * dimension and sharing the node coordinates array.
7796 * All cells of the *i*-th mesh precede all cells of the
7797 * (*i*+1)-th mesh within the result mesh.
7798 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7799 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7800 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7801 * is no more needed.
7802 * \throw If \a a.size() == 0.
7803 * \throw If \a a[ *i* ] == NULL.
7804 * \throw If the meshes do not share the node coordinates array.
7805 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7806 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7808 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7811 throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7812 for(std::size_t ii=0;ii<meshes.size();ii++)
7815 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7816 throw INTERP_KERNEL::Exception(oss.str().c_str());
7818 const DataArrayDouble *coords=meshes.front()->getCoords();
7819 int meshDim=meshes.front()->getMeshDimension();
7820 std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7822 int meshIndexLgth=0;
7823 for(;iter!=meshes.end();iter++)
7825 if(coords!=(*iter)->getCoords())
7826 throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7827 if(meshDim!=(*iter)->getMeshDimension())
7828 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7829 meshLgth+=(*iter)->getMeshLength();
7830 meshIndexLgth+=(*iter)->getNumberOfCells();
7832 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7833 nodal->alloc(meshLgth,1);
7834 int *nodalPtr=nodal->getPointer();
7835 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7836 nodalIndex->alloc(meshIndexLgth+1,1);
7837 int *nodalIndexPtr=nodalIndex->getPointer();
7839 for(iter=meshes.begin();iter!=meshes.end();iter++)
7841 const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7842 const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7843 int nbOfCells=(*iter)->getNumberOfCells();
7844 int meshLgth2=(*iter)->getMeshLength();
7845 nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7846 if(iter!=meshes.begin())
7847 nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7849 nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7852 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7853 ret->setName("merge");
7854 ret->setMeshDimension(meshDim);
7855 ret->setConnectivity(nodal,nodalIndex,true);
7856 ret->setCoords(coords);
7861 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7862 * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7863 * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7864 * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7865 * New" mode are returned for each input mesh.
7866 * \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7867 * \param [in] compType - specifies a cell comparison technique. For meaning of its
7868 * valid values [0,1,2], see zipConnectivityTraducer().
7869 * \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7870 * meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7871 * mesh. The caller is to delete each of the arrays using decrRef() as it is
7873 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7874 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7875 * is no more needed.
7876 * \throw If \a meshes.size() == 0.
7877 * \throw If \a meshes[ *i* ] == NULL.
7878 * \throw If the meshes do not share the node coordinates array.
7879 * \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7880 * \throw If the \a meshes are of different dimension (getMeshDimension()).
7881 * \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7882 * \throw If the nodal connectivity any of \a meshes includes an invalid id.
7884 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7886 //All checks are delegated to MergeUMeshesOnSameCoords
7887 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7888 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7889 corr.resize(meshes.size());
7890 std::size_t nbOfMeshes=meshes.size();
7892 const int *o2nPtr=o2n->getConstPointer();
7893 for(std::size_t i=0;i<nbOfMeshes;i++)
7895 DataArrayInt *tmp=DataArrayInt::New();
7896 int curNbOfCells=meshes[i]->getNumberOfCells();
7897 tmp->alloc(curNbOfCells,1);
7898 std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7899 offset+=curNbOfCells;
7900 tmp->setName(meshes[i]->getName());
7907 * Makes all given meshes share the nodal connectivity array. The common connectivity
7908 * array is created by concatenating the connectivity arrays of all given meshes. All
7909 * the given meshes must be of the same space dimension but dimension of cells **can
7910 * differ**. This method is particulary useful in MEDLoader context to build a \ref
7911 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7912 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7913 * \param [in,out] meshes - a vector of meshes to update.
7914 * \throw If any of \a meshes is NULL.
7915 * \throw If the coordinates array is not set in any of \a meshes.
7916 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7917 * \throw If \a meshes are of different space dimension.
7919 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
7921 std::size_t sz=meshes.size();
7924 std::vector< const DataArrayDouble * > coords(meshes.size());
7925 std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7926 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7930 (*it)->checkConnectivityFullyDefined();
7931 const DataArrayDouble *coo=(*it)->getCoords();
7936 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7937 oss << " has no coordinate array defined !";
7938 throw INTERP_KERNEL::Exception(oss.str().c_str());
7943 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7944 oss << " is null !";
7945 throw INTERP_KERNEL::Exception(oss.str().c_str());
7948 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7949 std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7950 int offset=(*it)->getNumberOfNodes();
7951 (*it++)->setCoords(res);
7952 for(;it!=meshes.end();it++)
7954 int oldNumberOfNodes=(*it)->getNumberOfNodes();
7955 (*it)->setCoords(res);
7956 (*it)->shiftNodeNumbersInConn(offset);
7957 offset+=oldNumberOfNodes;
7962 * Merges nodes coincident with a given precision within all given meshes that share
7963 * the nodal connectivity array. The given meshes **can be of different** mesh
7964 * dimension. This method is particulary useful in MEDLoader context to build a \ref
7965 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7966 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7967 * \param [in,out] meshes - a vector of meshes to update.
7968 * \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7969 * \throw If any of \a meshes is NULL.
7970 * \throw If the \a meshes do not share the same node coordinates array.
7971 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7973 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
7977 std::set<const DataArrayDouble *> s;
7978 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7981 s.insert((*it)->getCoords());
7984 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 !";
7985 throw INTERP_KERNEL::Exception(oss.str().c_str());
7990 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 !";
7991 throw INTERP_KERNEL::Exception(oss.str().c_str());
7993 const DataArrayDouble *coo=*(s.begin());
7997 DataArrayInt *comm,*commI;
7998 coo->findCommonTuples(eps,-1,comm,commI);
7999 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
8000 int oldNbOfNodes=coo->getNumberOfTuples();
8002 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
8003 if(oldNbOfNodes==newNbOfNodes)
8005 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
8006 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8008 (*it)->renumberNodesInConn(o2n->getConstPointer());
8009 (*it)->setCoords(newCoords);
8014 * 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.
8015 * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
8016 * \param isQuad specifies the policy of connectivity.
8017 * @ret in/out parameter in which the result will be append
8019 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
8021 INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
8022 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
8023 ret.push_back(cm.getExtrudedType());
8024 int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
8027 case INTERP_KERNEL::NORM_POINT1:
8029 ret.push_back(connBg[1]);
8030 ret.push_back(connBg[1]+nbOfNodesPerLev);
8033 case INTERP_KERNEL::NORM_SEG2:
8035 int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
8036 ret.insert(ret.end(),conn,conn+4);
8039 case INTERP_KERNEL::NORM_SEG3:
8041 int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8042 ret.insert(ret.end(),conn,conn+8);
8045 case INTERP_KERNEL::NORM_QUAD4:
8047 int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8048 ret.insert(ret.end(),conn,conn+8);
8051 case INTERP_KERNEL::NORM_TRI3:
8053 int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8054 ret.insert(ret.end(),conn,conn+6);
8057 case INTERP_KERNEL::NORM_TRI6:
8059 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,
8060 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8061 ret.insert(ret.end(),conn,conn+15);
8064 case INTERP_KERNEL::NORM_QUAD8:
8067 connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8068 connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8069 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8071 ret.insert(ret.end(),conn,conn+20);
8074 case INTERP_KERNEL::NORM_POLYGON:
8076 std::back_insert_iterator< std::vector<int> > ii(ret);
8077 std::copy(connBg+1,connEnd,ii);
8079 std::reverse_iterator<const int *> rConnBg(connEnd);
8080 std::reverse_iterator<const int *> rConnEnd(connBg+1);
8081 std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8082 std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8083 for(std::size_t i=0;i<nbOfRadFaces;i++)
8086 int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8087 std::copy(conn,conn+4,ii);
8092 throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8097 * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8099 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8102 double v[3]={0.,0.,0.};
8103 std::size_t sz=std::distance(begin,end);
8108 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];
8109 v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8110 v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8112 double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8114 // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8115 // SEG3 forming a circle):
8116 if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8118 v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8119 for(std::size_t j=0;j<sz;j++)
8121 if (j%2) // current point i is quadratic, next point i+1 is standard
8124 ip1 = (j+1)%sz; // ip1 = "i+1"
8126 else // current point i is standard, next point i+1 is quadratic
8131 v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8132 v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8133 v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8135 ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8141 * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8143 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8145 std::vector<std::pair<int,int> > edges;
8146 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8147 const int *bgFace=begin;
8148 for(std::size_t i=0;i<nbOfFaces;i++)
8150 const int *endFace=std::find(bgFace+1,end,-1);
8151 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8152 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8154 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8155 if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8157 edges.push_back(p1);
8161 return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8165 * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8167 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8169 double vec0[3],vec1[3];
8170 std::size_t sz=std::distance(begin,end);
8172 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8173 int nbOfNodes=(int)sz/2;
8174 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8175 const double *pt0=coords+3*begin[0];
8176 const double *pt1=coords+3*begin[nbOfNodes];
8177 vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8178 return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8181 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8183 std::size_t sz=std::distance(begin,end);
8184 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8185 std::size_t nbOfNodes(sz/2);
8186 std::copy(begin,end,(int *)tmp);
8187 for(std::size_t j=1;j<nbOfNodes;j++)
8189 begin[j]=tmp[nbOfNodes-j];
8190 begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8194 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8196 std::size_t sz=std::distance(begin,end);
8198 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8199 double vec0[3],vec1[3];
8200 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8201 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];
8202 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;
8205 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8207 std::size_t sz=std::distance(begin,end);
8209 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8211 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8212 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8213 return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8217 * 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 )
8218 * 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
8221 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8222 * \param [in] coords the coordinates with nb of components exactly equal to 3
8223 * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8224 * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8225 * \param [out] res the result is put at the end of the vector without any alteration of the data.
8227 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8229 int nbFaces=std::count(begin+1,end,-1)+1;
8230 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8231 double *vPtr=v->getPointer();
8232 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8233 double *pPtr=p->getPointer();
8234 const int *stFaceConn=begin+1;
8235 for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8237 const int *endFaceConn=std::find(stFaceConn,end,-1);
8238 ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8239 stFaceConn=endFaceConn+1;
8241 pPtr=p->getPointer(); vPtr=v->getPointer();
8242 DataArrayInt *comm1=0,*commI1=0;
8243 v->findCommonTuples(eps,-1,comm1,commI1);
8244 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8245 const int *comm1Ptr=comm1->getConstPointer();
8246 const int *commI1Ptr=commI1->getConstPointer();
8247 int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8248 res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8250 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8251 mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8252 mm->finishInsertingCells();
8254 for(int i=0;i<nbOfGrps1;i++)
8256 int vecId=comm1Ptr[commI1Ptr[i]];
8257 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8258 DataArrayInt *comm2=0,*commI2=0;
8259 tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8260 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8261 const int *comm2Ptr=comm2->getConstPointer();
8262 const int *commI2Ptr=commI2->getConstPointer();
8263 int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8264 for(int j=0;j<nbOfGrps2;j++)
8266 if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8268 res->insertAtTheEnd(begin,end);
8269 res->pushBackSilent(-1);
8273 int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8274 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8275 ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8276 DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8277 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8278 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8279 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8280 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8281 const int *idsNodePtr=idsNode->getConstPointer();
8282 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];
8283 double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8284 double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8285 if(std::abs(norm)>eps)
8287 double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8288 mm3->rotate(center,vec,angle);
8290 mm3->changeSpaceDimension(2);
8291 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8292 const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8293 const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8294 int nbOfCells=mm4->getNumberOfCells();
8295 for(int k=0;k<nbOfCells;k++)
8298 for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8299 res->pushBackSilent(idsNodePtr[*work]);
8300 res->pushBackSilent(-1);
8305 res->popBackSilent();
8309 * 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
8310 * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8312 * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8313 * \param [in] coords coordinates expected to have 3 components.
8314 * \param [in] begin start of the nodal connectivity of the face.
8315 * \param [in] end end of the nodal connectivity (excluded) of the face.
8316 * \param [out] v the normalized vector of size 3
8317 * \param [out] p the pos of plane
8319 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8321 std::size_t nbPoints=std::distance(begin,end);
8323 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8324 double vec[3]={0.,0.,0.};
8326 bool refFound=false;
8327 for(;j<nbPoints-1 && !refFound;j++)
8329 vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8330 vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8331 vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8332 double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8336 vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8339 for(std::size_t i=j;i<nbPoints-1;i++)
8342 curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8343 curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8344 curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8345 double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8348 curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8349 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];
8350 norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8353 v[0]/=norm; v[1]/=norm; v[2]/=norm;
8354 *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8358 throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8362 * This method tries to obtain a well oriented polyhedron.
8363 * If the algorithm fails, an exception will be thrown.
8365 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8367 std::list< std::pair<int,int> > edgesOK,edgesFinished;
8368 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8369 std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8371 int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8372 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8373 for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8375 while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8378 std::size_t smthChanged=0;
8379 for(std::size_t i=0;i<nbOfFaces;i++)
8381 endFace=std::find(bgFace+1,end,-1);
8382 nbOfEdgesInFace=std::distance(bgFace,endFace);
8386 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8388 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8389 std::pair<int,int> p2(p1.second,p1.first);
8390 bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8391 bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8392 if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8397 std::reverse(bgFace+1,endFace);
8398 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8400 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8401 std::pair<int,int> p2(p1.second,p1.first);
8402 if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8403 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8404 if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8405 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8406 std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8407 if(it!=edgesOK.end())
8410 edgesFinished.push_back(p1);
8413 edgesOK.push_back(p1);
8420 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8422 if(!edgesOK.empty())
8423 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8424 if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8425 {//not lucky ! The first face was not correctly oriented : reorient all faces...
8427 for(std::size_t i=0;i<nbOfFaces;i++)
8429 endFace=std::find(bgFace+1,end,-1);
8430 std::reverse(bgFace+1,endFace);
8436 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8438 int nbOfNodesExpected(skin->getNumberOfNodes());
8439 const int *n2oPtr(n2o->getConstPointer());
8440 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8441 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8442 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8443 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8444 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8445 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8446 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_POLYGON;
8447 if(nbOfNodesExpected<1)
8449 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8450 *work++=n2oPtr[prevNode];
8451 for(int i=1;i<nbOfNodesExpected;i++)
8453 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8455 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8456 conn.erase(prevNode);
8459 int curNode(*(conn.begin()));
8460 *work++=n2oPtr[curNode];
8461 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8462 shar.erase(prevCell);
8465 prevCell=*(shar.begin());
8469 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8472 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8475 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8480 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8482 int nbOfNodesExpected(skin->getNumberOfNodes());
8483 int nbOfTurn(nbOfNodesExpected/2);
8484 const int *n2oPtr(n2o->getConstPointer());
8485 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8486 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8487 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8488 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8489 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8490 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8491 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_QPOLYG;
8492 if(nbOfNodesExpected<1)
8494 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8495 *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8496 for(int i=1;i<nbOfTurn;i++)
8498 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8500 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8501 conn.erase(prevNode);
8504 int curNode(*(conn.begin()));
8505 *work=n2oPtr[curNode];
8506 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8507 shar.erase(prevCell);
8510 int curCell(*(shar.begin()));
8511 work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8517 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8520 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8523 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8529 * This method makes the assumption spacedimension == meshdimension == 2.
8530 * This method works only for linear cells.
8532 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8534 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8536 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8537 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8538 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8539 int oldNbOfNodes(skin->getNumberOfNodes());
8540 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8541 int nbOfNodesExpected(skin->getNumberOfNodes());
8542 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8543 int nbCells(skin->getNumberOfCells());
8544 if(nbCells==nbOfNodesExpected)
8545 return buildUnionOf2DMeshLinear(skin,n2o);
8546 else if(2*nbCells==nbOfNodesExpected)
8547 return buildUnionOf2DMeshQuadratic(skin,n2o);
8549 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8553 * This method makes the assumption spacedimension == meshdimension == 3.
8554 * This method works only for linear cells.
8556 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8558 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8560 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8561 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8562 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8563 const int *conn=m->getNodalConnectivity()->getConstPointer();
8564 const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8565 int nbOfCells=m->getNumberOfCells();
8566 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8567 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED;
8570 work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8571 for(int i=1;i<nbOfCells;i++)
8574 work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8580 * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8581 * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8583 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8587 for(int i=0;i<nbOfNodesInCell;i++)
8588 w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8589 else if(spaceDim==2)
8591 for(int i=0;i<nbOfNodesInCell;i++)
8593 w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8598 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8601 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8603 int nbOfCells=getNumberOfCells();
8605 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8606 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};
8607 ofs << " <" << getVTKDataSetType() << ">\n";
8608 ofs << " <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8609 ofs << " <PointData>\n" << pointData << std::endl;
8610 ofs << " </PointData>\n";
8611 ofs << " <CellData>\n" << cellData << std::endl;
8612 ofs << " </CellData>\n";
8613 ofs << " <Points>\n";
8614 if(getSpaceDimension()==3)
8615 _coords->writeVTK(ofs,8,"Points",byteData);
8618 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8619 coo->writeVTK(ofs,8,"Points",byteData);
8621 ofs << " </Points>\n";
8622 ofs << " <Cells>\n";
8623 const int *cPtr=_nodal_connec->getConstPointer();
8624 const int *cIPtr=_nodal_connec_index->getConstPointer();
8625 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8626 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8627 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8628 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8629 int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8630 int szFaceOffsets=0,szConn=0;
8631 for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8634 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8637 *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8638 w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8642 int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8643 *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8644 std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8645 *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8646 w4=std::copy(c.begin(),c.end(),w4);
8649 types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8650 types->writeVTK(ofs,8,"UInt8","types",byteData);
8651 offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8652 if(szFaceOffsets!=0)
8653 {//presence of Polyhedra
8654 connectivity->reAlloc(szConn);
8655 faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8656 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8657 w1=faces->getPointer();
8658 for(int i=0;i<nbOfCells;i++)
8659 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8661 int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8663 const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8664 for(int j=0;j<nbFaces;j++)
8666 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8667 *w1++=(int)std::distance(w6,w5);
8668 w1=std::copy(w6,w5,w1);
8672 faces->writeVTK(ofs,8,"Int32","faces",byteData);
8674 connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8675 ofs << " </Cells>\n";
8676 ofs << " </Piece>\n";
8677 ofs << " </" << getVTKDataSetType() << ">\n";
8680 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8682 stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8684 { stream << " Not set !"; return ; }
8685 stream << " Mesh dimension : " << _mesh_dim << ".";
8689 { stream << " No coordinates set !"; return ; }
8690 if(!_coords->isAllocated())
8691 { stream << " Coordinates set but not allocated !"; return ; }
8692 stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8693 stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8694 if(!_nodal_connec_index)
8695 { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8696 if(!_nodal_connec_index->isAllocated())
8697 { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8698 int lgth=_nodal_connec_index->getNumberOfTuples();
8699 int cpt=_nodal_connec_index->getNumberOfComponents();
8700 if(cpt!=1 || lgth<1)
8702 stream << std::endl << "Number of cells : " << lgth-1 << ".";
8705 std::string MEDCouplingUMesh::getVTKDataSetType() const
8707 return std::string("UnstructuredGrid");
8710 std::string MEDCouplingUMesh::getVTKFileExtension() const
8712 return std::string("vtu");
8716 * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8717 * returns a result mesh constituted by polygons.
8718 * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8719 * all nodes from m2.
8720 * The meshes should be in 2D space. In
8721 * addition, returns two arrays mapping cells of the result mesh to cells of the input
8723 * \param [in] m1 - the first input mesh which is a partitioned object.
8724 * \param [in] m2 - the second input mesh which is a partition tool.
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 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8742 double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8745 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
8746 m1->checkFullyDefined();
8747 m2->checkFullyDefined();
8748 if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8749 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!");
8751 // Step 1: compute all edge intersections (new nodes)
8752 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8753 MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
8754 DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8755 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
8756 IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
8757 m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8758 addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
8759 revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8760 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8761 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8763 // Step 2: re-order newly created nodes according to the ordering found in m2
8764 std::vector< std::vector<int> > intersectEdge2;
8765 BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8766 subDiv2.clear(); dd5=0; dd6=0;
8769 std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8770 std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8771 BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8772 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8774 // Step 4: Prepare final result:
8775 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
8776 addCooDa->alloc((int)(addCoo.size())/2,2);
8777 std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8778 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
8779 addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8780 std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8781 std::vector<const DataArrayDouble *> coordss(4);
8782 coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8783 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
8784 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
8785 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8786 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8787 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8788 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8789 ret->setConnectivity(conn,connI,true);
8790 ret->setCoords(coo);
8791 cellNb1=c1.retn(); cellNb2=c2.retn();
8795 bool IsColinearOfACellOf(const std::vector< std::vector<int> >& intersectEdge1, const std::vector<int>& candidates, int start, int stop, int& retVal)
8797 if(candidates.empty())
8799 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
8801 const std::vector<int>& pool(intersectEdge1[*it]);
8802 int tmp[2]; tmp[0]=start; tmp[1]=stop;
8803 if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
8808 tmp[0]=stop; tmp[1]=start;
8809 if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
8818 //tony to put in private of MEDCouplingUMesh
8819 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,
8820 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInRetColinear, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInMesh1DForIdsInRetColinear)
8822 idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1);
8823 idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1);
8824 int nCells(mesh1D->getNumberOfCells());
8825 if(nCells!=(int)intersectEdge2.size())
8826 throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
8827 const DataArrayDouble *coo2(mesh1D->getCoords());
8828 const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
8829 const double *coo2Ptr(coo2->begin());
8830 int offset1(coords1->getNumberOfTuples());
8831 int offset2(offset1+coo2->getNumberOfTuples());
8832 int offset3(offset2+addCoo.size()/2);
8833 std::vector<double> addCooQuad;
8834 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
8835 int tmp[4],cicnt(0),kk(0);
8836 for(int i=0;i<nCells;i++)
8838 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
8839 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
8840 const std::vector<int>& subEdges(intersectEdge2[i]);
8841 int nbSubEdge(subEdges.size()/2);
8842 for(int j=0;j<nbSubEdge;j++,kk++)
8844 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));
8845 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
8846 INTERP_KERNEL::Edge *e2Ptr(e2);
8847 std::map<int,int>::const_iterator itm;
8848 if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
8850 tmp[0]=INTERP_KERNEL::NORM_SEG3;
8851 itm=mergedNodes.find(subEdges[2*j]);
8852 tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
8853 itm=mergedNodes.find(subEdges[2*j+1]);
8854 tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
8855 tmp[3]=offset3+(int)addCooQuad.size()/2;
8857 e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2);
8859 cOut->insertAtTheEnd(tmp,tmp+4);
8860 ciOut->pushBackSilent(cicnt);
8864 tmp[0]=INTERP_KERNEL::NORM_SEG2;
8865 itm=mergedNodes.find(subEdges[2*j]);
8866 tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
8867 itm=mergedNodes.find(subEdges[2*j+1]);
8868 tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
8870 cOut->insertAtTheEnd(tmp,tmp+3);
8871 ciOut->pushBackSilent(cicnt);
8874 if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00))
8876 idsInRetColinear->pushBackSilent(kk);
8877 idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00);
8882 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
8883 ret->setConnectivity(cOut,ciOut,true);
8884 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr3(DataArrayDouble::New());
8885 arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
8886 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
8887 std::vector<const DataArrayDouble *> coordss(4);
8888 coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
8889 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
8890 ret->setCoords(arr);
8894 MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
8896 std::vector<int> allEdges;
8897 for(const int *it2(descBg);it2!=descEnd;it2++)
8899 const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
8901 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
8903 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
8905 std::size_t nb(allEdges.size());
8907 throw INTERP_KERNEL::Exception("BuildRefined2DCell : internal error 1 !");
8908 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
8909 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
8910 ret->setCoords(coords);
8911 ret->allocateCells(1);
8912 std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
8913 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
8914 connOut[kk]=allEdges[2*kk];
8915 ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]);
8919 void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector<int>& conn, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edges)
8922 for(std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >::const_iterator it=edges.begin();it!=edges.end();it++)
8924 const INTERP_KERNEL::Edge *ee(*it);
8925 if(dynamic_cast<const INTERP_KERNEL::EdgeArcCircle *>(ee))
8929 mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]);
8932 const double *coo(mesh2D->getCoords()->begin());
8933 std::size_t sz(conn.size());
8934 std::vector<double> addCoo;
8935 std::vector<int> conn2(conn);
8936 int offset(mesh2D->getNumberOfNodes());
8937 for(std::size_t i=0;i<sz;i++)
8940 edges[(i+1)%sz]->getMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);
8941 addCoo.insert(addCoo.end(),tmp,tmp+2);
8942 conn2.push_back(offset+(int)i);
8944 mesh2D->getCoords()->rearrange(1);
8945 mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size());
8946 mesh2D->getCoords()->rearrange(2);
8947 mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]);
8951 MEDCouplingUMesh *BuildMesh2DCutFrom(int cellIdInMesh2D, const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh2DDesc, const MEDCouplingUMesh *splitMesh1D,
8952 const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1, int offset,
8953 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
8955 idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(splitMesh1D->getNumberOfCells(),2);
8956 int *idsLeftRightPtr(idsLeftRight->getPointer());
8957 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
8958 ret->setCoords(splitMesh1D->getCoords());
8959 ret->allocateCells();
8960 int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells());
8961 if(nbCellsInSplitMesh1D==0)
8962 throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error ! input 1D mesh must have at least one cell !");
8963 const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin()),
8964 *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin());
8966 std::vector<int> allEdges;
8967 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > allEdgesPtr;
8968 for(const int *it(descBg);it!=descEnd;it++)
8970 int edgeId(std::abs(*it)-1);
8971 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
8972 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m));
8973 const std::vector<int>& edge1(intersectEdge1[edgeId]);
8975 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
8977 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
8978 std::size_t sz(edge1.size());
8979 for(std::size_t cnt=0;cnt<sz;cnt++)
8980 allEdgesPtr.push_back(ee);
8982 std::size_t nb(allEdges.size()),ii,jj;
8984 throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !");
8985 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
8986 std::vector<int> edge1Bis(nb*2);
8987 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edge1BisPtr(nb*2);
8988 std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin());
8989 std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb);
8990 std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin());
8991 std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb);
8993 for(int iStart=0;iStart<nbCellsInSplitMesh1D;)
8996 for(;iEnd<nbCellsInSplitMesh1D;)
8998 for(jj=0;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd]+2];jj++);
9004 if(iEnd<nbCellsInSplitMesh1D)
9007 for(ii=0;ii<nb && edge1Bis[2*ii]!=cSplitPtr[ciSplitPtr[iStart]+1];ii++);
9008 for(jj=ii;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd-1]+2];jj++);
9011 {//the edges splitMesh1D[iStart:iEnd] does not fully cut the current 2D cell -> single output cell
9012 std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9013 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edgesPtr(nbOfEdgesOf2DCellSplit);
9014 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9016 connOut[kk]=edge1Bis[2*kk];
9017 edgesPtr[kk]=edge1BisPtr[2*kk];
9019 AddCellInMesh2D(ret,connOut,edgesPtr);
9020 for(int mm=iStart;mm<iEnd;mm++)
9022 idsLeftRightPtr[2*mm]=offset;
9023 idsLeftRightPtr[2*mm+1]=offset;
9028 // [i,iEnd[ contains the
9029 std::vector<int> connOutLeft,connOutRight;//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1]
9030 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > eleft,eright;
9031 for(std::size_t k=ii;k<jj+1;k++)
9032 { connOutLeft.push_back(edge1Bis[2*k+1]); eleft.push_back(edge1BisPtr[2*k+1]); }
9033 for(int ik=iEnd-1;ik>=iStart;ik--)
9035 connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]);
9036 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9037 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9038 eleft.push_back(ee);
9040 for(std::size_t k=jj+1;k<nbOfEdgesOf2DCellSplit+ii;k++)
9041 { connOutRight.push_back(edge1Bis[2*k+1]); eright.push_back(edge1BisPtr[2*k+1]); }
9042 for(int ik=iStart;ik<iEnd;ik++)
9044 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9045 connOutRight.push_back(cSplitPtr[ciSplitPtr[ik]+2]);
9046 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9047 eright.push_back(ee);
9049 AddCellInMesh2D(ret,connOutLeft,eleft);
9050 AddCellInMesh2D(ret,connOutRight,eright);
9051 for(int mm=iStart;mm<iEnd;mm++)
9053 idsLeftRightPtr[2*mm]=offset;
9054 idsLeftRightPtr[2*mm+1]=offset+1;
9064 * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
9065 * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
9066 * all nodes from \a mesh1D.
9067 * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
9069 * \param [in] mesh2D - the 2D mesh (spacedim=meshdim=2) to be intersected using \a mesh1D tool.
9070 * \param [in] mesh1D - the 1D mesh (spacedim=2 meshdim=1) the is the tool that will be used to intersect \a mesh2D.
9071 * \param [in] eps - precision used to perform intersections and localization operations.
9072 * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
9073 * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
9074 * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
9075 * 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.
9076 * \param [out] cellIdInMesh1D - the array that gives for each cell id \a i in \a splitMesh1D the 1 or 2 id(s) in \a splitMesh2D that \a i shares.
9077 * 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.
9079 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
9081 if(!mesh2D || !mesh1D)
9082 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
9083 mesh2D->checkFullyDefined();
9084 mesh1D->checkFullyDefined();
9085 const std::vector<std::string>& compNames(mesh2D->getCoords()->getInfoOnComponents());
9086 if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
9087 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
9088 // Step 1: compute all edge intersections (new nodes)
9089 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9090 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
9091 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9092 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9094 // Build desc connectivity
9095 DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
9096 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9097 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
9098 std::map<int,int> mergedNodes;
9099 Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes);
9100 // use mergeNodes to fix intersectEdge1
9101 for(std::vector< std::vector<int> >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++)
9103 std::size_t n((*it0).size()/2);
9104 int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]);
9105 std::map<int,int>::const_iterator it1;
9106 it1=mergedNodes.find(eltStart);
9107 if(it1!=mergedNodes.end())
9108 (*it0)[0]=(*it1).second;
9109 it1=mergedNodes.find(eltEnd);
9110 if(it1!=mergedNodes.end())
9111 (*it0)[2*n-1]=(*it1).second;
9114 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9115 addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9116 // Step 2: re-order newly created nodes according to the ordering found in m2
9117 std::vector< std::vector<int> > intersectEdge2;
9118 BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
9121 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear;
9122 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2(DataArrayInt::New()); ret2->alloc(0,1);
9123 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1,
9124 idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear));
9125 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(-1); ret3->rearrange(2);
9126 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells()));
9127 // deal with cells in mesh2D that are not cut but only some of their edges are
9128 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCpy());
9129 idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1);
9130 idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique();
9131 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s;//ids in mesh2D that are impacted by the fact that some edges of \a mesh1D are part of those cells
9132 if(!idsInDesc2DToBeRefined->empty())
9134 DataArrayInt *out0(0),*outi0(0);
9135 MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
9136 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> outi0s(outi0);
9138 out0s=out0s->buildUnique();
9142 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1NonCol(static_cast<MEDCouplingUMesh *>(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end())));
9143 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> baryRet1(ret1NonCol->getBarycenterAndOwner());
9144 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elts,eltsIndex;
9145 mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
9146 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex2(eltsIndex->deltaShiftIndex());
9147 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex3(eltsIndex2->getIdsEqual(1));
9148 if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells())
9149 throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !");
9150 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToBeModified(elts->buildUnique());
9151 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells()));
9152 if((DataArrayInt *)out0s)
9153 untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one
9154 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > outMesh2DSplit;
9155 if(!untouchedCells->empty())
9157 outMesh2DSplit.push_back(static_cast<MEDCouplingUMesh *>(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end())));
9158 outMesh2DSplit.back()->setCoords(ret1->getCoords());
9159 ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end());
9161 if((DataArrayInt *)out0s)
9162 {// here dealing with cells in out0s but not in cellsToBeModified
9163 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fewModifiedCells(out0s->buildSubstraction(cellsToBeModified));
9164 const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin());
9165 for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++)
9167 outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1));
9169 int offset(ret2->getNumberOfTuples());
9170 ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end());
9171 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1);
9172 partOfRet3->fillWithValue(-1); partOfRet3->rearrange(2);
9173 int kk(0),*ret3ptr(partOfRet3->getPointer());
9174 for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++)
9176 int faceId(std::abs(*it)-1);
9177 for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++)
9179 int tmp(fewModifiedCells->locateValue(*it2));
9182 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9183 ret3ptr[2*kk]=tmp+offset;
9184 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9185 ret3ptr[2*kk+1]=tmp+offset;
9188 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : internal error 1 !");
9191 ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true);
9193 for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++)
9195 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell(elts->getIdsEqual(*it));
9196 idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end());
9197 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end()));
9198 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfMesh1CuttingCur2DCell(static_cast<MEDCouplingUMesh *>(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end())));
9199 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3;
9200 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> splitOfOneCell(BuildMesh2DCutFrom(*it,mesh2D,m1Desc,partOfMesh1CuttingCur2DCell,dd1->begin()+dd2->getIJ(*it,0),dd1->begin()+dd2->getIJ((*it)+1,0),intersectEdge1,ret2->getNumberOfTuples(),partOfRet3));
9201 ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true);
9202 outMesh2DSplit.push_back(splitOfOneCell);
9203 for(int i=0;i<splitOfOneCell->getNumberOfCells();i++)
9204 ret2->pushBackSilent(*it);
9207 std::size_t nbOfMeshes(outMesh2DSplit.size());
9208 std::vector<const MEDCouplingUMesh *> tmp(nbOfMeshes);
9209 for(std::size_t i=0;i<nbOfMeshes;i++)
9210 tmp[i]=outMesh2DSplit[i];
9212 ret1->getCoords()->setInfoOnComponents(compNames);
9214 splitMesh1D=ret1.retn();
9215 splitMesh2D=MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp);
9216 cellIdInMesh2D=ret2.retn();
9217 cellIdInMesh1D=ret3.retn();
9221 * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
9222 * (newly created) nodes corresponding to the edge intersections.
9224 * @param[out] cr, crI connectivity of the resulting mesh
9225 * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
9226 * TODO: describe input parameters
9228 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
9229 const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
9230 const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
9231 const std::vector<double>& addCoords,
9232 std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
9234 static const int SPACEDIM=2;
9235 const double *coo1(m1->getCoords()->getConstPointer());
9236 const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer());
9237 int offset1(m1->getNumberOfNodes());
9238 const double *coo2(m2->getCoords()->getConstPointer());
9239 const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer());
9240 int offset2(offset1+m2->getNumberOfNodes());
9241 int offset3(offset2+((int)addCoords.size())/2);
9242 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
9243 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9244 // Here a BBTree on 2D-cells, not on segments:
9245 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
9246 int ncell1(m1->getNumberOfCells());
9248 for(int i=0;i<ncell1;i++)
9250 std::vector<int> candidates2;
9251 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9252 std::map<INTERP_KERNEL::Node *,int> mapp;
9253 std::map<int,INTERP_KERNEL::Node *> mappRev;
9254 INTERP_KERNEL::QuadraticPolygon pol1;
9255 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
9256 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
9257 // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
9258 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
9259 // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
9260 pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
9261 desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
9263 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
9264 std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
9265 INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
9266 for(it1.first();!it1.finished();it1.next())
9267 edges1.insert(it1.current()->getPtr());
9269 std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
9270 std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
9272 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9274 INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
9275 const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
9276 // Complete mapping with elements coming from the current cell it2 in mesh2:
9277 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
9278 // pol2 is the new QP in the final merged result.
9279 pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
9280 pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
9283 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9285 INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
9286 pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
9287 //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
9288 pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9290 // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
9291 // by m2 but that we still want to keep in the final result.
9296 INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9298 catch(INTERP_KERNEL::Exception& e)
9300 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();
9301 throw INTERP_KERNEL::Exception(oss.str().c_str());
9304 for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
9305 (*it).second->decrRef();
9309 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
9311 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> nTmp(n); nTmp->incrRef();
9312 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>::const_iterator it(m.find(nTmp));
9314 throw INTERP_KERNEL::Exception("Internal error in remapping !");
9315 int v((*it).second);
9316 if(v==forbVal0 || v==forbVal1)
9318 if(std::find(isect.begin(),isect.end(),v)==isect.end())
9322 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
9327 bool presenceOfOn(false);
9328 for(int i=0;i<sz;i++)
9330 INTERP_KERNEL::ElementaryEdge *e(c[i]);
9331 if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
9333 IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
9334 IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
9336 return presenceOfOn;
9340 * 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.
9341 * 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.
9342 * 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.
9343 * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to avoid to have a non conform mesh.
9345 * \return int - the number of new nodes created (in most of cases 0).
9347 * \throw If \a this is not coherent.
9348 * \throw If \a this has not spaceDim equal to 2.
9349 * \throw If \a this has not meshDim equal to 2.
9350 * \throw If some subcells needed to be split are orphan.
9351 * \sa MEDCouplingUMesh::conformize2D
9353 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
9355 if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
9356 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
9357 desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
9358 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
9359 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
9360 if(midOpt==0 && midOptI==0)
9362 split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
9365 else if(midOpt!=0 && midOptI!=0)
9366 return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
9368 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
9372 * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
9373 * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
9374 * 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
9375 * 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).
9376 * 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.
9378 * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
9379 * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
9381 * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
9382 * This method expects that all nodes in \a this are not closer than \a eps.
9383 * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
9385 * \param [in] eps the relative error to detect merged edges.
9386 * \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
9387 * that the user is expected to deal with.
9389 * \throw If \a this is not coherent.
9390 * \throw If \a this has not spaceDim equal to 2.
9391 * \throw If \a this has not meshDim equal to 2.
9392 * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
9394 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
9396 static const int SPACEDIM=2;
9398 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
9399 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
9400 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
9401 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
9402 const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
9403 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
9404 const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
9405 int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
9406 std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
9407 std::vector<double> addCoo;
9408 BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
9409 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9410 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9411 for(int i=0;i<nDescCell;i++)
9413 std::vector<int> candidates;
9414 myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
9415 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
9418 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9419 INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
9420 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
9421 INTERP_KERNEL::MergePoints merge;
9422 INTERP_KERNEL::QuadraticPolygon c1,c2;
9423 e1->intersectWith(e2,merge,c1,c2);
9424 e1->decrRef(); e2->decrRef();
9425 if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
9426 overlapEdge[i].push_back(*it);
9427 if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
9428 overlapEdge[*it].push_back(i);
9431 // splitting done. sort intersect point in intersectEdge.
9432 std::vector< std::vector<int> > middle(nDescCell);
9433 int nbOf2DCellsToBeSplit(0);
9434 bool middleNeedsToBeUsed(false);
9435 std::vector<bool> cells2DToTreat(nDescCell,false);
9436 for(int i=0;i<nDescCell;i++)
9438 std::vector<int>& isect(intersectEdge[i]);
9439 int sz((int)isect.size());
9442 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9443 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
9444 e->sortSubNodesAbs(coords,isect);
9449 int idx0(rdi[i]),idx1(rdi[i+1]);
9451 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
9452 if(!cells2DToTreat[rd[idx0]])
9454 cells2DToTreat[rd[idx0]]=true;
9455 nbOf2DCellsToBeSplit++;
9457 // try to reuse at most eventual 'middle' of SEG3
9458 std::vector<int>& mid(middle[i]);
9459 mid.resize(sz+1,-1);
9460 if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
9462 middleNeedsToBeUsed=true;
9463 const std::vector<int>& candidates(overlapEdge[i]);
9464 std::vector<int> trueCandidates;
9465 for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
9466 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
9467 trueCandidates.push_back(*itc);
9468 int stNode(c[ci[i]+1]),endNode(isect[0]);
9469 for(int j=0;j<sz+1;j++)
9471 for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
9473 int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
9474 if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
9475 { mid[j]=*itc; break; }
9478 endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
9483 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
9484 if(nbOf2DCellsToBeSplit==0)
9487 int *retPtr(ret->getPointer());
9488 for(int i=0;i<nCell;i++)
9489 if(cells2DToTreat[i])
9492 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
9493 DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
9494 MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
9495 DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
9496 if(middleNeedsToBeUsed)
9497 { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
9498 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
9499 int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
9500 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.
9501 setPartOfMySelf(ret->begin(),ret->end(),*modif);
9503 bool areNodesMerged; int newNbOfNodes;
9504 if(nbOfNodesCreated!=0)
9505 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
9511 * 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.
9512 * 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).
9513 * 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
9514 * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
9515 * 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
9516 * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
9518 * 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
9519 * using new instance, idem for coordinates.
9521 * 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.
9523 * \return DataArrayInt * - The list of cellIds in \a this that have at least one edge colinearized.
9525 * \throw If \a this is not coherent.
9526 * \throw If \a this has not spaceDim equal to 2.
9527 * \throw If \a this has not meshDim equal to 2.
9529 * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
9531 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
9533 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
9535 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
9536 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
9537 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9538 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9539 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
9540 const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
9541 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
9542 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
9543 const double *coords(_coords->begin());
9544 int *newciptr(newci->getPointer());
9545 for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
9547 if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
9548 ret->pushBackSilent(i);
9549 newciptr[1]=newc->getNumberOfTuples();
9554 if(!appendedCoords->empty())
9556 appendedCoords->rearrange(2);
9557 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
9559 setCoords(newCoords);
9562 setConnectivity(newc,newci,true);
9567 * \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.
9568 * 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.
9569 * And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
9570 * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
9571 * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
9572 * \param [out] addCoo - nodes to be append at the end
9573 * \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.
9575 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
9576 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)
9578 static const int SPACEDIM=2;
9579 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9580 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9581 const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer());
9582 // Build BB tree of all edges in the tool mesh (second mesh)
9583 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
9584 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9585 int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
9586 intersectEdge1.resize(nDescCell1);
9587 colinear2.resize(nDescCell2);
9588 subDiv2.resize(nDescCell2);
9589 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
9591 std::vector<int> candidates1(1);
9592 int offset1(m1Desc->getNumberOfNodes());
9593 int offset2(offset1+m2Desc->getNumberOfNodes());
9594 for(int i=0;i<nDescCell1;i++) // for all edges in the first mesh
9596 std::vector<int> candidates2; // edges of mesh2 candidate for intersection
9597 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9598 if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
9600 std::map<INTERP_KERNEL::Node *,int> map1,map2;
9601 // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
9602 INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
9604 INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
9605 // 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
9606 // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
9607 std::set<INTERP_KERNEL::Node *> nodes;
9608 pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
9609 std::size_t szz(nodes.size());
9610 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
9611 std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
9612 for(std::size_t iii=0;iii<szz;iii++,itt++)
9613 { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
9614 // end of protection
9615 // Performs egde cutting:
9616 pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes);
9621 intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
9626 * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
9627 * It builds the descending connectivity of the two meshes, and then using a binary tree
9628 * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
9629 * Documentation about parameters colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
9631 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
9632 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
9633 MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
9634 std::vector<double>& addCoo,
9635 MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
9637 // Build desc connectivity
9638 desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
9639 desc2=DataArrayInt::New();
9640 descIndx2=DataArrayInt::New();
9641 revDesc2=DataArrayInt::New();
9642 revDescIndx2=DataArrayInt::New();
9643 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9644 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
9645 m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
9646 m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
9647 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
9648 std::map<int,int> notUsedMap;
9649 Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap);
9650 m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
9651 m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
9655 * This method performs the 2nd step of Partition of 2D mesh.
9656 * This method has 4 inputs :
9657 * - a mesh 'm1' with meshDim==1 and a SpaceDim==2
9658 * - a mesh 'm2' with meshDim==1 and a SpaceDim==2
9659 * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
9660 * 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'
9661 * Nodes end up lying consecutively on a cutted edge.
9662 * \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.
9663 * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
9664 * \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.
9665 * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
9666 * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
9668 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
9669 const std::vector<double>& addCoo,
9670 const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
9672 int offset1=m1->getNumberOfNodes();
9673 int ncell=m2->getNumberOfCells();
9674 const int *c=m2->getNodalConnectivity()->getConstPointer();
9675 const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
9676 const double *coo=m2->getCoords()->getConstPointer();
9677 const double *cooBis=m1->getCoords()->getConstPointer();
9678 int offset2=offset1+m2->getNumberOfNodes();
9679 intersectEdge.resize(ncell);
9680 for(int i=0;i<ncell;i++,cI++)
9682 const std::vector<int>& divs=subDiv[i];
9683 int nnode=cI[1]-cI[0]-1;
9684 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
9685 std::map<INTERP_KERNEL::Node *, int> mapp22;
9686 for(int j=0;j<nnode;j++)
9688 INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
9689 int nnid=c[(*cI)+j+1];
9690 mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
9691 mapp22[nn]=nnid+offset1;
9693 INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
9694 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
9695 ((*it).second.first)->decrRef();
9696 std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
9697 std::map<INTERP_KERNEL::Node *,int> mapp3;
9698 for(std::size_t j=0;j<divs.size();j++)
9701 INTERP_KERNEL::Node *tmp=0;
9703 tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
9705 tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
9707 tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
9711 e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
9712 for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
9719 * 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).
9720 * 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
9721 * with a plane. The result will be put in 'cut3DSuf' out parameter.
9722 * \param [in] cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
9723 * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
9724 * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
9725 * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
9726 * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
9727 * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
9728 * \param [in] desc is the descending connectivity 3DSurf->3DCurve
9729 * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
9730 * \param [out] cut3DSuf input/output param.
9732 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
9733 const int *nodal3DCurve, const int *nodalIndx3DCurve,
9734 const int *desc, const int *descIndx,
9735 std::vector< std::pair<int,int> >& cut3DSurf)
9737 std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
9738 int nbOf3DSurfCell=(int)cut3DSurf.size();
9739 for(int i=0;i<nbOf3DSurfCell;i++)
9741 std::vector<int> res;
9742 int offset=descIndx[i];
9743 int nbOfSeg=descIndx[i+1]-offset;
9744 for(int j=0;j<nbOfSeg;j++)
9746 int edgeId=desc[offset+j];
9747 int status=cut3DCurve[edgeId];
9751 res.push_back(status);
9754 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
9755 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
9763 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
9769 std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
9770 std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
9773 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
9777 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
9782 {// case when plane is on a multi colinear edge of a polyhedron
9783 if((int)res.size()==2*nbOfSeg)
9785 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
9788 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
9795 * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
9796 * 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).
9797 * 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
9798 * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
9799 * \param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
9800 * \param desc is the descending connectivity 3D->3DSurf
9801 * \param descIndx is the descending connectivity index 3D->3DSurf
9803 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
9804 const int *desc, const int *descIndx,
9805 DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
9807 checkFullyDefined();
9808 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
9809 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
9810 const int *nodal3D=_nodal_connec->getConstPointer();
9811 const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
9812 int nbOfCells=getNumberOfCells();
9813 for(int i=0;i<nbOfCells;i++)
9815 std::map<int, std::set<int> > m;
9816 int offset=descIndx[i];
9817 int nbOfFaces=descIndx[i+1]-offset;
9820 for(int j=0;j<nbOfFaces;j++)
9822 const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
9823 if(p.first!=-1 && p.second!=-1)
9827 start=p.first; end=p.second;
9828 m[p.first].insert(p.second);
9829 m[p.second].insert(p.first);
9833 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
9834 int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
9835 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
9836 INTERP_KERNEL::NormalizedCellType cmsId;
9837 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
9838 start=tmp[0]; end=tmp[nbOfNodesSon-1];
9839 for(unsigned k=0;k<nbOfNodesSon;k++)
9841 m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
9842 m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
9849 std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
9853 std::map<int, std::set<int> >::const_iterator it=m.find(start);
9854 const std::set<int>& s=(*it).second;
9855 std::set<int> s2; s2.insert(prev);
9857 std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
9860 int val=*s3.begin();
9861 conn.push_back(start);
9868 conn.push_back(end);
9871 nodalRes->insertAtTheEnd(conn.begin(),conn.end());
9872 nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
9873 cellIds->pushBackSilent(i);
9879 * 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
9880 * 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
9881 * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
9882 * 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
9883 * 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.
9885 * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
9887 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
9889 std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
9892 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
9893 if(cm.getDimension()==2)
9895 const int *node=nodalConnBg+1;
9896 int startNode=*node++;
9897 double refX=coords[2*startNode];
9898 for(;node!=nodalConnEnd;node++)
9900 if(coords[2*(*node)]<refX)
9903 refX=coords[2*startNode];
9906 std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
9910 double angle0=-M_PI/2;
9915 double angleNext=0.;
9916 while(nextNode!=startNode)
9920 for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
9922 if(*node!=tmpOut.back() && *node!=prevNode)
9924 tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
9925 double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
9930 res=angle0-angleM+2.*M_PI;
9939 if(nextNode!=startNode)
9941 angle0=angleNext-M_PI;
9944 prevNode=tmpOut.back();
9945 tmpOut.push_back(nextNode);
9948 std::vector<int> tmp3(2*(sz-1));
9949 std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
9950 std::copy(nodalConnBg+1,nodalConnEnd,it);
9951 if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
9953 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
9956 if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
9958 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
9963 nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
9964 nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
9969 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
9972 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
9976 * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
9977 * 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.
9979 * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
9980 * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
9981 * \param [in,out] arr array in which the remove operation will be done.
9982 * \param [in,out] arrIndx array in the remove operation will modify
9983 * \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])
9984 * \return true if \b arr and \b arrIndx have been modified, false if not.
9986 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
9988 if(!arrIndx || !arr)
9989 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
9990 if(offsetForRemoval<0)
9991 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
9992 std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
9993 int nbOfGrps=arrIndx->getNumberOfTuples()-1;
9994 int *arrIPtr=arrIndx->getPointer();
9997 const int *arrPtr=arr->getConstPointer();
9998 std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
9999 for(int i=0;i<nbOfGrps;i++,arrIPtr++)
10001 if(*arrIPtr-previousArrI>offsetForRemoval)
10003 for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
10005 if(s.find(*work)==s.end())
10006 arrOut.push_back(*work);
10009 previousArrI=*arrIPtr;
10010 *arrIPtr=(int)arrOut.size();
10012 if(arr->getNumberOfTuples()==(int)arrOut.size())
10014 arr->alloc((int)arrOut.size(),1);
10015 std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
10020 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10021 * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
10022 * The selection of extraction is done standardly in new2old format.
10023 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10025 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10026 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10027 * \param [in] arrIn arr origin array from which the extraction will be done.
10028 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10029 * \param [out] arrOut the resulting array
10030 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10031 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
10033 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10034 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10036 if(!arrIn || !arrIndxIn)
10037 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
10038 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10039 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10040 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
10041 std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
10042 const int *arrInPtr=arrIn->getConstPointer();
10043 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10044 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10046 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10047 int maxSizeOfArr=arrIn->getNumberOfTuples();
10048 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10049 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10050 arrIo->alloc((int)(sz+1),1);
10051 const int *idsIt=idsOfSelectBg;
10052 int *work=arrIo->getPointer();
10055 for(std::size_t i=0;i<sz;i++,work++,idsIt++)
10057 if(*idsIt>=0 && *idsIt<nbOfGrps)
10058 lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
10061 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10062 throw INTERP_KERNEL::Exception(oss.str().c_str());
10068 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
10069 oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
10070 throw INTERP_KERNEL::Exception(oss.str().c_str());
10073 arro->alloc(lgth,1);
10074 work=arro->getPointer();
10075 idsIt=idsOfSelectBg;
10076 for(std::size_t i=0;i<sz;i++,idsIt++)
10078 if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
10079 work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
10082 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
10083 oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10084 throw INTERP_KERNEL::Exception(oss.str().c_str());
10087 arrOut=arro.retn();
10088 arrIndexOut=arrIo.retn();
10092 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10093 * 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 ).
10094 * The selection of extraction is done standardly in new2old format.
10095 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10097 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10098 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10099 * \param [in] arrIn arr origin array from which the extraction will be done.
10100 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10101 * \param [out] arrOut the resulting array
10102 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10103 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
10105 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10106 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10108 if(!arrIn || !arrIndxIn)
10109 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
10110 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10111 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10112 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
10113 int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
10114 const int *arrInPtr=arrIn->getConstPointer();
10115 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10116 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10118 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10119 int maxSizeOfArr=arrIn->getNumberOfTuples();
10120 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10121 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10122 arrIo->alloc((int)(sz+1),1);
10123 int idsIt=idsOfSelectStart;
10124 int *work=arrIo->getPointer();
10127 for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
10129 if(idsIt>=0 && idsIt<nbOfGrps)
10130 lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
10133 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10134 throw INTERP_KERNEL::Exception(oss.str().c_str());
10140 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
10141 oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
10142 throw INTERP_KERNEL::Exception(oss.str().c_str());
10145 arro->alloc(lgth,1);
10146 work=arro->getPointer();
10147 idsIt=idsOfSelectStart;
10148 for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
10150 if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
10151 work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
10154 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
10155 oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10156 throw INTERP_KERNEL::Exception(oss.str().c_str());
10159 arrOut=arro.retn();
10160 arrIndexOut=arrIo.retn();
10164 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10165 * 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
10166 * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
10167 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
10169 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10170 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10171 * \param [in] arrIn arr origin array from which the extraction will be done.
10172 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10173 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
10174 * \param [in] srcArrIndex index array of \b srcArr
10175 * \param [out] arrOut the resulting array
10176 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10178 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
10180 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10181 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
10182 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10184 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10185 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
10186 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10187 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10188 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10189 std::vector<bool> v(nbOfTuples,true);
10191 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10192 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10193 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10195 if(*it>=0 && *it<nbOfTuples)
10198 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
10202 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
10203 throw INTERP_KERNEL::Exception(oss.str().c_str());
10206 srcArrIndexPtr=srcArrIndex->getConstPointer();
10207 arrIo->alloc(nbOfTuples+1,1);
10208 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
10209 const int *arrInPtr=arrIn->getConstPointer();
10210 const int *srcArrPtr=srcArr->getConstPointer();
10211 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
10212 int *arroPtr=arro->getPointer();
10213 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
10217 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
10218 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
10222 std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
10223 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
10224 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
10227 arrOut=arro.retn();
10228 arrIndexOut=arrIo.retn();
10232 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10233 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
10235 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10236 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10237 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
10238 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10239 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
10240 * \param [in] srcArrIndex index array of \b srcArr
10242 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
10244 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
10245 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
10247 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10248 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
10249 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10250 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10251 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10252 int *arrInOutPtr=arrInOut->getPointer();
10253 const int *srcArrPtr=srcArr->getConstPointer();
10254 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10256 if(*it>=0 && *it<nbOfTuples)
10258 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
10259 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
10262 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] !";
10263 throw INTERP_KERNEL::Exception(oss.str().c_str());
10268 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
10269 throw INTERP_KERNEL::Exception(oss.str().c_str());
10275 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
10276 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
10277 * 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]].
10278 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
10279 * A negative value in \b arrIn means that it is ignored.
10280 * 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.
10282 * \param [in] arrIn arr origin array from which the extraction will be done.
10283 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10284 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
10285 * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
10287 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
10289 int seed=0,nbOfDepthPeelingPerformed=0;
10290 return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
10294 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
10295 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
10296 * 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]].
10297 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
10298 * A negative value in \b arrIn means that it is ignored.
10299 * 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.
10300 * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
10301 * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
10302 * \param [in] arrIn arr origin array from which the extraction will be done.
10303 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10304 * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
10305 * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
10306 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
10307 * \sa MEDCouplingUMesh::partitionBySpreadZone
10309 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
10311 nbOfDepthPeelingPerformed=0;
10313 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
10314 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10317 DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
10321 std::vector<bool> fetched(nbOfTuples,false);
10322 return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
10325 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
10327 nbOfDepthPeelingPerformed=0;
10328 if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
10329 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
10330 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10331 std::vector<bool> fetched2(nbOfTuples,false);
10333 for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
10335 if(*seedElt>=0 && *seedElt<nbOfTuples)
10336 { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
10338 { 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()); }
10340 const int *arrInPtr=arrIn->getConstPointer();
10341 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10342 int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
10343 std::vector<int> idsToFetch1(seedBg,seedEnd);
10344 std::vector<int> idsToFetch2;
10345 std::vector<int> *idsToFetch=&idsToFetch1;
10346 std::vector<int> *idsToFetchOther=&idsToFetch2;
10347 while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
10349 for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
10350 for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
10352 { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
10353 std::swap(idsToFetch,idsToFetchOther);
10354 idsToFetchOther->clear();
10355 nbOfDepthPeelingPerformed++;
10357 int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
10359 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
10360 int *retPtr=ret->getPointer();
10361 for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
10368 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10369 * 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
10370 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
10371 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
10373 * \param [in] start begin of set of ids of the input extraction (included)
10374 * \param [in] end end of set of ids of the input extraction (excluded)
10375 * \param [in] step step of the set of ids in range mode.
10376 * \param [in] arrIn arr origin array from which the extraction will be done.
10377 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10378 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
10379 * \param [in] srcArrIndex index array of \b srcArr
10380 * \param [out] arrOut the resulting array
10381 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10383 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
10385 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10386 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
10387 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10389 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10390 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
10391 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10392 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10393 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10395 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10396 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10397 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
10399 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
10401 if(it>=0 && it<nbOfTuples)
10402 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
10405 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
10406 throw INTERP_KERNEL::Exception(oss.str().c_str());
10409 srcArrIndexPtr=srcArrIndex->getConstPointer();
10410 arrIo->alloc(nbOfTuples+1,1);
10411 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
10412 const int *arrInPtr=arrIn->getConstPointer();
10413 const int *srcArrPtr=srcArr->getConstPointer();
10414 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
10415 int *arroPtr=arro->getPointer();
10416 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
10418 int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
10421 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
10422 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
10426 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
10427 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
10430 arrOut=arro.retn();
10431 arrIndexOut=arrIo.retn();
10435 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10436 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
10438 * \param [in] start begin of set of ids of the input extraction (included)
10439 * \param [in] end end of set of ids of the input extraction (excluded)
10440 * \param [in] step step of the set of ids in range mode.
10441 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
10442 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10443 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
10444 * \param [in] srcArrIndex index array of \b srcArr
10446 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
10448 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
10449 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
10451 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10452 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
10453 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10454 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10455 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10456 int *arrInOutPtr=arrInOut->getPointer();
10457 const int *srcArrPtr=srcArr->getConstPointer();
10458 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
10460 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
10462 if(it>=0 && it<nbOfTuples)
10464 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
10465 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
10468 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
10469 throw INTERP_KERNEL::Exception(oss.str().c_str());
10474 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
10475 throw INTERP_KERNEL::Exception(oss.str().c_str());
10481 * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
10482 * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
10483 * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
10484 * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
10485 * The sum of measure field of returned mesh is equal to the sum of measure field of this.
10487 * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
10489 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
10491 checkFullyDefined();
10492 int mdim=getMeshDimension();
10493 int spaceDim=getSpaceDimension();
10495 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
10496 std::vector<DataArrayInt *> partition=partitionBySpreadZone();
10497 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
10498 std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
10499 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
10500 ret->setCoords(getCoords());
10501 ret->allocateCells((int)partition.size());
10503 for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
10505 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
10506 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
10510 cell=tmp->buildUnionOf2DMesh();
10513 cell=tmp->buildUnionOf3DMesh();
10516 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
10519 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
10522 ret->finishInsertingCells();
10527 * This method partitions \b this into contiguous zone.
10528 * This method only needs a well defined connectivity. Coordinates are not considered here.
10529 * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
10531 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
10533 int nbOfCellsCur=getNumberOfCells();
10534 std::vector<DataArrayInt *> ret;
10535 if(nbOfCellsCur<=0)
10537 DataArrayInt *neigh=0,*neighI=0;
10538 computeNeighborsOfCells(neigh,neighI);
10539 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
10540 std::vector<bool> fetchedCells(nbOfCellsCur,false);
10541 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
10543 while(seed<nbOfCellsCur)
10545 int nbOfPeelPerformed=0;
10546 ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
10547 seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
10549 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
10550 ret.push_back((*it).retn());
10555 * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
10556 * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
10558 * \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.
10559 * \return a newly allocated DataArrayInt to be managed by the caller.
10560 * \throw In case of \a code has not the right format (typically of size 3*n)
10562 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
10564 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
10565 std::size_t nb=code.size()/3;
10566 if(code.size()%3!=0)
10567 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
10568 ret->alloc((int)nb,2);
10569 int *retPtr=ret->getPointer();
10570 for(std::size_t i=0;i<nb;i++,retPtr+=2)
10572 retPtr[0]=code[3*i+2];
10573 retPtr[1]=code[3*i+2]+code[3*i+1];
10579 * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
10580 * All cells in \a this are expected to be linear 3D cells.
10581 * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
10582 * It leads to an increase to number of cells.
10583 * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
10584 * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints
10585 * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
10587 * \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.
10588 * For all other cells, the splitting policy will be ignored.
10589 * \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.
10590 * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
10591 * an id of old cell producing it. The caller is to delete this array using
10592 * decrRef() as it is no more needed.
10593 * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
10595 * \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
10596 * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
10598 * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
10599 * \throw If \a this is not fully constituted with linear 3D cells.
10600 * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
10602 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
10604 INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
10605 checkConnectivityFullyDefined();
10606 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10607 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
10608 int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
10609 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
10610 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
10611 int *retPt(ret->getPointer());
10612 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
10613 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
10614 const int *oldc(_nodal_connec->begin());
10615 const int *oldci(_nodal_connec_index->begin());
10616 const double *coords(_coords->begin());
10617 for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
10619 std::vector<int> a; std::vector<double> b;
10620 INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
10621 std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
10622 const int *aa(&a[0]);
10625 for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
10627 *it=(-(*(it))-1+nbNodes);
10628 addPts->insertAtTheEnd(b.begin(),b.end());
10629 nbNodes+=(int)b.size()/3;
10631 for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
10632 newConn->insertAtTheEnd(aa,aa+4);
10634 if(!addPts->empty())
10636 addPts->rearrange(3);
10637 nbOfAdditionalPoints=addPts->getNumberOfTuples();
10638 addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
10639 ret0->setCoords(addPts);
10643 nbOfAdditionalPoints=0;
10644 ret0->setCoords(getCoords());
10646 ret0->setNodalConnectivity(newConn);
10648 ret->computeOffsets2();
10649 n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
10650 return ret0.retn();
10654 * 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).
10656 * \sa MEDCouplingUMesh::split2DCells
10658 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
10660 checkConnectivityFullyDefined();
10661 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
10662 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
10663 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
10664 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
10665 int prevPosOfCi(ciPtr[0]);
10666 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
10668 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
10669 *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
10670 for(int j=0;j<sz;j++)
10672 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
10673 for(int k=0;k<sz2;k++)
10674 *cPtr++=subPtr[offset2+k];
10676 *cPtr++=oldConn[prevPosOfCi+j+2];
10679 prevPosOfCi=ciPtr[1];
10680 ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
10683 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
10684 _nodal_connec->decrRef();
10685 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
10688 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
10694 int ret(nodesCnter++);
10696 e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
10697 addCoo.insertAtTheEnd(newPt,newPt+2);
10704 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)
10707 int trueStart(start>=0?start:nbOfEdges+start);
10708 tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
10709 newConnOfCell->insertAtTheEnd(tmp,tmp+3);
10714 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
10715 InternalAddPoint(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
10716 middles.push_back(tmp3+offset);
10719 middles.push_back(connBg[trueStart+nbOfEdges]);
10723 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)
10725 int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
10726 newConnOfCell->pushBackSilent(tmpEnd);
10731 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
10732 InternalAddPoint(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
10733 middles.push_back(tmp3+offset);
10736 middles.push_back(connBg[start+nbOfEdges]);
10740 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)
10746 int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
10747 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
10748 InternalAddPoint(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
10749 middles.push_back(tmp3+offset);
10752 middles.push_back(connBg[start+nbOfEdges]);
10759 * 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 ) .
10760 * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
10762 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
10764 std::size_t sz(std::distance(connBg,connEnd));
10765 if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
10766 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
10768 INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
10769 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
10770 unsigned nbs(cm.getNumberOfSons2(connBg+1,sz)),nbOfHit(0);
10771 int posBaseElt(0),posEndElt(0),nbOfTurn(0);
10772 INTERP_KERNEL::NormalizedCellType typeOfSon;
10773 std::vector<int> middles;
10775 for(;nbOfHit<nbs;nbOfTurn++)
10777 cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
10778 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10779 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
10782 unsigned endI(nbs-nbOfHit);
10783 for(unsigned i=0;i<endI;i++)
10785 cm.fillSonCellNodalConnectivity2(posBaseElt+(int)i+1,connBg+1,sz,tmpConn,typeOfSon);
10786 INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
10787 INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
10788 bool isColinear(eint->areColinears());
10800 {//look if the first edge of cell is not colinear with last edges in this case the start of nodal connectivity is shifted back
10801 unsigned endII(nbs-nbOfHit-1);//warning nbOfHit can be modified, so put end condition in a variable.
10802 for(unsigned ii=0;ii<endII;ii++)
10804 cm.fillSonCellNodalConnectivity2(nbs-ii-1,connBg+1,sz,tmpConn,typeOfSon);
10805 eCand=MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m);
10806 eint=INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand);
10807 isColinear=eint->areColinears();
10823 //push [posBaseElt,posEndElt) in newConnOfCell using e
10825 EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
10826 else if(nbOfHit!=nbs)
10827 EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
10829 EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
10830 posBaseElt=posEndElt;
10833 if(!middles.empty())
10834 newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
10839 * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
10841 * \return int - the number of new nodes created.
10842 * \sa MEDCouplingUMesh::split2DCells
10844 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
10847 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
10848 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
10849 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
10850 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
10851 const int *midPtr(mid->begin()),*midIPtr(midI->begin());
10852 const double *oldCoordsPtr(getCoords()->begin());
10853 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
10854 int prevPosOfCi(ciPtr[0]);
10855 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
10857 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
10858 for(int j=0;j<sz;j++)
10859 { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
10860 *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
10861 for(int j=0;j<sz;j++)//loop over subedges of oldConn
10863 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
10867 cPtr[1]=oldConn[prevPosOfCi+2+j];
10868 cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
10871 std::vector<INTERP_KERNEL::Node *> ns(3);
10872 ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
10873 ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
10874 ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
10875 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
10876 for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
10878 cPtr[1]=subPtr[offset2+k];
10879 cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
10881 int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
10883 { cPtr[1]=tmpEnd; }
10884 cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
10886 prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
10887 ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
10890 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
10891 _nodal_connec->decrRef();
10892 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
10893 addCoo->rearrange(2);
10894 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
10896 return addCoo->getNumberOfTuples();
10899 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
10900 _own_cell(true),_cell_id(-1),_nb_cell(0)
10905 _nb_cell=mesh->getNumberOfCells();
10909 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
10917 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
10918 _own_cell(false),_cell_id(bg-1),
10925 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
10928 if(_cell_id<_nb_cell)
10937 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
10943 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
10945 return new MEDCouplingUMeshCellByTypeIterator(_mesh);
10948 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
10954 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
10962 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
10968 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
10973 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
10978 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
10980 return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
10983 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
10988 _nb_cell=mesh->getNumberOfCells();
10992 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
10999 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
11001 const int *c=_mesh->getNodalConnectivity()->getConstPointer();
11002 const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
11003 if(_cell_id<_nb_cell)
11005 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
11006 int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
11007 int startId=_cell_id;
11008 _cell_id+=nbOfElems;
11009 return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
11015 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
11019 _conn=mesh->getNodalConnectivity()->getPointer();
11020 _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
11024 void MEDCouplingUMeshCell::next()
11026 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11031 _conn_lgth=_conn_indx[1]-_conn_indx[0];
11034 std::string MEDCouplingUMeshCell::repr() const
11036 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11038 std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
11040 std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
11044 return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
11047 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
11049 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11050 return (INTERP_KERNEL::NormalizedCellType)_conn[0];
11052 return INTERP_KERNEL::NORM_ERROR;
11055 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
11058 if(_conn_lgth!=NOTICABLE_FIRST_VAL)