1 // Copyright (C) 2007-2015 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 // Author : Anthony Geay (CEA/DEN)
21 #include "MEDCouplingUMesh.hxx"
22 #include "MEDCoupling1GTUMesh.hxx"
23 #include "MEDCouplingMemArray.txx"
24 #include "MEDCouplingFieldDouble.hxx"
25 #include "CellModel.hxx"
26 #include "VolSurfUser.txx"
27 #include "InterpolationUtils.hxx"
28 #include "PointLocatorAlgos.txx"
30 #include "BBTreeDst.txx"
31 #include "SplitterTetra.hxx"
32 #include "DirectedBoundingBox.hxx"
33 #include "InterpKernelMatrixTools.hxx"
34 #include "InterpKernelMeshQuality.hxx"
35 #include "InterpKernelCellSimplify.hxx"
36 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
37 #include "InterpKernelAutoPtr.hxx"
38 #include "InterpKernelGeo2DNode.hxx"
39 #include "InterpKernelGeo2DEdgeLin.hxx"
40 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
41 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
50 using namespace ParaMEDMEM;
52 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
54 const INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::MEDMEM_ORDER[N_MEDMEM_ORDER] = { INTERP_KERNEL::NORM_POINT1, INTERP_KERNEL::NORM_SEG2, INTERP_KERNEL::NORM_SEG3, INTERP_KERNEL::NORM_SEG4, INTERP_KERNEL::NORM_POLYL, INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_TRI7, INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_QUAD9, INTERP_KERNEL::NORM_POLYGON, INTERP_KERNEL::NORM_QPOLYG, INTERP_KERNEL::NORM_TETRA4, INTERP_KERNEL::NORM_PYRA5, INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXA8, INTERP_KERNEL::NORM_HEXGP12, INTERP_KERNEL::NORM_TETRA10, INTERP_KERNEL::NORM_PYRA13, INTERP_KERNEL::NORM_PENTA15, INTERP_KERNEL::NORM_HEXA20, INTERP_KERNEL::NORM_HEXA27, INTERP_KERNEL::NORM_POLYHED };
56 MEDCouplingUMesh *MEDCouplingUMesh::New()
58 return new MEDCouplingUMesh;
61 MEDCouplingUMesh *MEDCouplingUMesh::New(const std::string& meshName, int meshDim)
63 MEDCouplingUMesh *ret=new MEDCouplingUMesh;
64 ret->setName(meshName);
65 ret->setMeshDimension(meshDim);
70 * Returns a new MEDCouplingMesh which is a full copy of \a this one. No data is shared
71 * between \a this and the new mesh.
72 * \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
73 * delete this mesh using decrRef() as it is no more needed.
75 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
81 * Returns a new MEDCouplingMesh which is a copy of \a this one.
82 * \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
83 * this mesh are shared by the new mesh.
84 * \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
85 * delete this mesh using decrRef() as it is no more needed.
87 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
89 return new MEDCouplingUMesh(*this,recDeepCpy);
93 * This method behaves mostly like MEDCouplingUMesh::deepCpy method, except that only nodal connectivity arrays are deeply copied.
94 * The coordinates are shared between \a this and the returned instance.
96 * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
97 * \sa MEDCouplingUMesh::deepCpy
99 MEDCouplingPointSet *MEDCouplingUMesh::deepCpyConnectivityOnly() const
101 checkConnectivityFullyDefined();
102 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=clone(false);
103 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(getNodalConnectivity()->deepCpy()),ci(getNodalConnectivityIndex()->deepCpy());
104 ret->setConnectivity(c,ci);
108 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other)
111 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
112 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
114 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
115 MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
116 setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
119 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
121 std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
125 std::vector<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildrenWithNull() const
127 std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildrenWithNull());
128 ret.push_back(_nodal_connec);
129 ret.push_back(_nodal_connec_index);
133 void MEDCouplingUMesh::updateTime() const
135 MEDCouplingPointSet::updateTime();
138 updateTimeWith(*_nodal_connec);
140 if(_nodal_connec_index)
142 updateTimeWith(*_nodal_connec_index);
146 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
151 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
152 * then \a this mesh is most probably is writable, exchangeable and available for most
153 * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
154 * this method to check that all is in order with \a this mesh.
155 * \throw If the mesh dimension is not set.
156 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
157 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
158 * \throw If the connectivity data array has more than one component.
159 * \throw If the connectivity data array has a named component.
160 * \throw If the connectivity index data array has more than one component.
161 * \throw If the connectivity index data array has a named component.
163 void MEDCouplingUMesh::checkCoherency() const
166 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
168 MEDCouplingPointSet::checkCoherency();
169 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
171 if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
173 std::ostringstream message;
174 message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
175 throw INTERP_KERNEL::Exception(message.str().c_str());
180 if(_nodal_connec->getNumberOfComponents()!=1)
181 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
182 if(_nodal_connec->getInfoOnComponent(0)!="")
183 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
187 throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
188 if(_nodal_connec_index)
190 if(_nodal_connec_index->getNumberOfComponents()!=1)
191 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
192 if(_nodal_connec_index->getInfoOnComponent(0)!="")
193 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
197 throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
201 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
202 * then \a this mesh is most probably is writable, exchangeable and available for all
203 * algorithms. <br> In addition to the checks performed by checkCoherency(), this
204 * method thoroughly checks the nodal connectivity.
205 * \param [in] eps - a not used parameter.
206 * \throw If the mesh dimension is not set.
207 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
208 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
209 * \throw If the connectivity data array has more than one component.
210 * \throw If the connectivity data array has a named component.
211 * \throw If the connectivity index data array has more than one component.
212 * \throw If the connectivity index data array has a named component.
213 * \throw If number of nodes defining an element does not correspond to the type of element.
214 * \throw If the nodal connectivity includes an invalid node id.
216 void MEDCouplingUMesh::checkCoherency1(double eps) const
221 int meshDim=getMeshDimension();
222 int nbOfNodes=getNumberOfNodes();
223 int nbOfCells=getNumberOfCells();
224 const int *ptr=_nodal_connec->getConstPointer();
225 const int *ptrI=_nodal_connec_index->getConstPointer();
226 for(int i=0;i<nbOfCells;i++)
228 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
229 if((int)cm.getDimension()!=meshDim)
231 std::ostringstream oss;
232 oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
233 throw INTERP_KERNEL::Exception(oss.str().c_str());
235 int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
237 if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
239 std::ostringstream oss;
240 oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " << cm.getNumberOfNodes();
241 oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
242 throw INTERP_KERNEL::Exception(oss.str().c_str());
244 for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
249 if(nodeId>=nbOfNodes)
251 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes !";
252 throw INTERP_KERNEL::Exception(oss.str().c_str());
257 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " in connectivity ! sounds bad !";
258 throw INTERP_KERNEL::Exception(oss.str().c_str());
262 if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
264 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #-1 in connectivity ! sounds bad !";
265 throw INTERP_KERNEL::Exception(oss.str().c_str());
274 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
275 * then \a this mesh is most probably is writable, exchangeable and available for all
276 * algorithms. <br> This method performs the same checks as checkCoherency1() does.
277 * \param [in] eps - a not used parameter.
278 * \throw If the mesh dimension is not set.
279 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
280 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
281 * \throw If the connectivity data array has more than one component.
282 * \throw If the connectivity data array has a named component.
283 * \throw If the connectivity index data array has more than one component.
284 * \throw If the connectivity index data array has a named component.
285 * \throw If number of nodes defining an element does not correspond to the type of element.
286 * \throw If the nodal connectivity includes an invalid node id.
288 void MEDCouplingUMesh::checkCoherency2(double eps) const
290 checkCoherency1(eps);
294 * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
295 * elements contained in the mesh. For more info on the mesh dimension see
296 * \ref MEDCouplingUMeshPage.
297 * \param [in] meshDim - a new mesh dimension.
298 * \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
300 void MEDCouplingUMesh::setMeshDimension(int meshDim)
302 if(meshDim<-1 || meshDim>3)
303 throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
309 * Allocates memory to store an estimation of the given number of cells. Closer is the estimation to the number of cells effectively inserted,
310 * less will be the needs to realloc. If the number of cells to be inserted is not known simply put 0 to this parameter.
311 * If a nodal connectivity previouly existed before the call of this method, it will be reset.
313 * \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
315 * \if ENABLE_EXAMPLES
316 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
317 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
320 void MEDCouplingUMesh::allocateCells(int nbOfCells)
323 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
324 if(_nodal_connec_index)
326 _nodal_connec_index->decrRef();
330 _nodal_connec->decrRef();
332 _nodal_connec_index=DataArrayInt::New();
333 _nodal_connec_index->reserve(nbOfCells+1);
334 _nodal_connec_index->pushBackSilent(0);
335 _nodal_connec=DataArrayInt::New();
336 _nodal_connec->reserve(2*nbOfCells);
342 * Appends a cell to the connectivity array. For deeper understanding what is
343 * happening see \ref MEDCouplingUMeshNodalConnectivity.
344 * \param [in] type - type of cell to add.
345 * \param [in] size - number of nodes constituting this cell.
346 * \param [in] nodalConnOfCell - the connectivity of the cell to add.
348 * \if ENABLE_EXAMPLES
349 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
350 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
353 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
355 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
356 if(_nodal_connec_index==0)
357 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
358 if((int)cm.getDimension()==_mesh_dim)
361 if(size!=(int)cm.getNumberOfNodes())
363 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
364 oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
365 throw INTERP_KERNEL::Exception(oss.str().c_str());
367 int idx=_nodal_connec_index->back();
369 _nodal_connec_index->pushBackSilent(val);
370 _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
375 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
376 oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
377 oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
378 throw INTERP_KERNEL::Exception(oss.str().c_str());
383 * Compacts data arrays to release unused memory. This method is to be called after
384 * finishing cell insertion using \a this->insertNextCell().
386 * \if ENABLE_EXAMPLES
387 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
388 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
391 void MEDCouplingUMesh::finishInsertingCells()
393 _nodal_connec->pack();
394 _nodal_connec_index->pack();
395 _nodal_connec->declareAsNew();
396 _nodal_connec_index->declareAsNew();
401 * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
402 * Useful for python users.
404 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
406 return new MEDCouplingUMeshCellIterator(this);
410 * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
411 * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
412 * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
413 * Useful for python users.
415 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
417 if(!checkConsecutiveCellTypes())
418 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
419 return new MEDCouplingUMeshCellByTypeEntry(this);
423 * Returns a set of all cell types available in \a this mesh.
424 * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
425 * \warning this method does not throw any exception even if \a this is not defined.
426 * \sa MEDCouplingUMesh::getAllGeoTypesSorted
428 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
434 * This method returns the sorted list of geometric types in \a this.
435 * Sorted means in the same order than the cells in \a this. A single entry in return vector means the maximal chunk of consecutive cells in \a this
436 * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
438 * \throw if connectivity in \a this is not correctly defined.
440 * \sa MEDCouplingMesh::getAllGeoTypes
442 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
444 std::vector<INTERP_KERNEL::NormalizedCellType> ret;
445 checkConnectivityFullyDefined();
446 int nbOfCells(getNumberOfCells());
449 if(getMeshLength()<1)
450 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
451 const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
452 ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
453 for(int i=1;i<nbOfCells;i++,ci++)
454 if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
455 ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
460 * This method is a method that compares \a this and \a other.
461 * This method compares \b all attributes, even names and component names.
463 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
466 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
467 std::ostringstream oss; oss.precision(15);
468 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
471 reason="mesh given in input is not castable in MEDCouplingUMesh !";
474 if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
476 if(_mesh_dim!=otherC->_mesh_dim)
478 oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" << otherC->_mesh_dim;
482 if(_types!=otherC->_types)
484 oss << "umesh geometric type mismatch :\nThis geometric types are :";
485 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
486 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
487 oss << "\nOther geometric types are :";
488 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
489 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
493 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
494 if(_nodal_connec==0 || otherC->_nodal_connec==0)
496 reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
499 if(_nodal_connec!=otherC->_nodal_connec)
500 if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
502 reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
505 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
506 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
508 reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
511 if(_nodal_connec_index!=otherC->_nodal_connec_index)
512 if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
514 reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
521 * Checks if data arrays of this mesh (node coordinates, nodal
522 * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
524 * \param [in] other - the mesh to compare with.
525 * \param [in] prec - precision value used to compare node coordinates.
526 * \return bool - \a true if the two meshes are same.
528 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
530 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
533 if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
535 if(_mesh_dim!=otherC->_mesh_dim)
537 if(_types!=otherC->_types)
539 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
540 if(_nodal_connec==0 || otherC->_nodal_connec==0)
542 if(_nodal_connec!=otherC->_nodal_connec)
543 if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
545 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
546 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
548 if(_nodal_connec_index!=otherC->_nodal_connec_index)
549 if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
555 * Checks if \a this and \a other meshes are geometrically equivalent with high
556 * probability, else an exception is thrown. The meshes are considered equivalent if
557 * (1) meshes contain the same number of nodes and the same number of elements of the
558 * same types (2) three cells of the two meshes (first, last and middle) are based
559 * on coincident nodes (with a specified precision).
560 * \param [in] other - the mesh to compare with.
561 * \param [in] prec - the precision used to compare nodes of the two meshes.
562 * \throw If the two meshes do not match.
564 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
566 MEDCouplingPointSet::checkFastEquivalWith(other,prec);
567 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
569 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !");
573 * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
574 * cells each node belongs to.
575 * \warning For speed reasons, this method does not check if node ids in the nodal
576 * connectivity correspond to the size of node coordinates array.
577 * \param [in,out] revNodal - an array holding ids of cells sharing each node.
578 * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
579 * dividing cell ids in \a revNodal into groups each referring to one
580 * node. Its every element (except the last one) is an index pointing to the
581 * first id of a group of cells. For example cells sharing the node #1 are
582 * described by following range of indices:
583 * [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
584 * \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
585 * Number of cells sharing the *i*-th node is
586 * \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
587 * \throw If the coordinates array is not set.
588 * \throw If the nodal connectivity of cells is not defined.
590 * \if ENABLE_EXAMPLES
591 * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
592 * \ref py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
595 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
598 int nbOfNodes=getNumberOfNodes();
599 int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
600 revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
601 std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
602 const int *conn=_nodal_connec->getConstPointer();
603 const int *connIndex=_nodal_connec_index->getConstPointer();
604 int nbOfCells=getNumberOfCells();
605 int nbOfEltsInRevNodal=0;
606 for(int eltId=0;eltId<nbOfCells;eltId++)
608 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
609 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
610 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
611 if(*iter>=0)//for polyhedrons
613 nbOfEltsInRevNodal++;
614 revNodalIndxPtr[(*iter)+1]++;
617 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
618 int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
619 revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
620 std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
621 for(int eltId=0;eltId<nbOfCells;eltId++)
623 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
624 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
625 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
626 if(*iter>=0)//for polyhedrons
627 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
633 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
638 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
644 if(cm.getOrientationStatus(nb,conn1,conn2))
651 class MinusOneSonsGenerator
654 MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
655 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
656 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
657 static const int DELTA=1;
659 const INTERP_KERNEL::CellModel& _cm;
662 class MinusOneSonsGeneratorBiQuadratic
665 MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
666 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
667 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
668 static const int DELTA=1;
670 const INTERP_KERNEL::CellModel& _cm;
673 class MinusTwoSonsGenerator
676 MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
677 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
678 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
679 static const int DELTA=2;
681 const INTERP_KERNEL::CellModel& _cm;
687 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
688 * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
689 * describing correspondence between cells of \a this and the result meshes are
690 * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
691 * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
692 * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
693 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
694 * \warning For speed reasons, this method does not check if node ids in the nodal
695 * connectivity correspond to the size of node coordinates array.
696 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
697 * to write this mesh to the MED file, its cells must be sorted using
698 * sortCellsInMEDFileFrmt().
699 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
700 * each cell of \a this mesh.
701 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
702 * dividing cell ids in \a desc into groups each referring to one
703 * cell of \a this mesh. Its every element (except the last one) is an index
704 * pointing to the first id of a group of cells. For example cells of the
705 * result mesh bounding the cell #1 of \a this mesh are described by following
707 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
708 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
709 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
710 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
711 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
712 * by each cell of the result mesh.
713 * \param [in,out] revDescIndx - the array, of length one more than number of cells
714 * in the result mesh,
715 * dividing cell ids in \a revDesc into groups each referring to one
716 * cell of the result mesh the same way as \a descIndx divides \a desc.
717 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
718 * delete this mesh using decrRef() as it is no more needed.
719 * \throw If the coordinates array is not set.
720 * \throw If the nodal connectivity of cells is node defined.
721 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
722 * revDescIndx == NULL.
724 * \if ENABLE_EXAMPLES
725 * \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
726 * \ref py_mcumesh_buildDescendingConnectivity "Here is a Python example".
728 * \sa buildDescendingConnectivity2()
730 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
732 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
736 * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
737 * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
738 * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
739 * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
740 * \sa MEDCouplingUMesh::buildDescendingConnectivity
742 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
745 if(getMeshDimension()!=3)
746 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
747 return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
751 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
752 * this->getMeshDimension(), that bound cells of \a this mesh. In
753 * addition arrays describing correspondence between cells of \a this and the result
754 * meshes are returned. The arrays \a desc and \a descIndx describe the descending
755 * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
756 * mesh. This method differs from buildDescendingConnectivity() in that apart
757 * from cell ids, \a desc returns mutual orientation of cells in \a this and the
758 * result meshes. So a positive id means that order of nodes in corresponding cells
759 * of two meshes is same, and a negative id means a reverse order of nodes. Since a
760 * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
761 * i.e. cell ids are one-based.
762 * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
763 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
764 * \warning For speed reasons, this method does not check if node ids in the nodal
765 * connectivity correspond to the size of node coordinates array.
766 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
767 * to write this mesh to the MED file, its cells must be sorted using
768 * sortCellsInMEDFileFrmt().
769 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
770 * each cell of \a this mesh.
771 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
772 * dividing cell ids in \a desc into groups each referring to one
773 * cell of \a this mesh. Its every element (except the last one) is an index
774 * pointing to the first id of a group of cells. For example cells of the
775 * result mesh bounding the cell #1 of \a this mesh are described by following
777 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
778 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
779 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
780 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
781 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
782 * by each cell of the result mesh.
783 * \param [in,out] revDescIndx - the array, of length one more than number of cells
784 * in the result mesh,
785 * dividing cell ids in \a revDesc into groups each referring to one
786 * cell of the result mesh the same way as \a descIndx divides \a desc.
787 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
788 * shares the node coordinates array with \a this mesh. The caller is to
789 * delete this mesh using decrRef() as it is no more needed.
790 * \throw If the coordinates array is not set.
791 * \throw If the nodal connectivity of cells is node defined.
792 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
793 * revDescIndx == NULL.
795 * \if ENABLE_EXAMPLES
796 * \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
797 * \ref py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
799 * \sa buildDescendingConnectivity()
801 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
803 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
807 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
808 * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
809 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
810 * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
812 * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
813 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
814 * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
816 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
818 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
819 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
820 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
821 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
822 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
824 ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
828 * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
829 * This method is useful for users that want to reduce along a criterion the set of neighbours cell. This is typically the case to extract a set a neighbours,
830 * excluding a set of meshdim-1 cells in input descending connectivity.
831 * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
832 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
833 * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
835 * \param [in] desc descending connectivity array.
836 * \param [in] descIndx descending connectivity index array used to walk through \b desc.
837 * \param [in] revDesc reverse descending connectivity array.
838 * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
839 * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
840 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
841 * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
843 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
844 DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx)
846 if(!desc || !descIndx || !revDesc || !revDescIndx)
847 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
848 const int *descPtr=desc->getConstPointer();
849 const int *descIPtr=descIndx->getConstPointer();
850 const int *revDescPtr=revDesc->getConstPointer();
851 const int *revDescIPtr=revDescIndx->getConstPointer();
853 int nbCells=descIndx->getNumberOfTuples()-1;
854 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
855 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
856 int *out1Ptr=out1->getPointer();
858 out0->reserve(desc->getNumberOfTuples());
859 for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
861 for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
863 std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
865 out0->insertAtTheEnd(s.begin(),s.end());
867 *out1Ptr=out0->getNumberOfTuples();
869 neighbors=out0.retn();
870 neighborsIndx=out1.retn();
874 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
875 * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
876 * This method lists node by node in \b this which are its neighbors. To compute the result only connectivities are considered.
877 * The neighbor nodes of node having id 'nodeId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
879 * \param [out] neighbors is an array storing all the neighbors of all nodes in \b this. This array is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
880 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
881 * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
883 void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayInt *&neighbors, DataArrayInt *&neighborsIdx) const
886 int mdim(getMeshDimension()),nbNodes(getNumberOfNodes());
887 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descIndx(DataArrayInt::New()),revDesc(DataArrayInt::New()),revDescIndx(DataArrayInt::New());
888 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh1D;
893 mesh1D=explode3DMeshTo1D(desc,descIndx,revDesc,revDescIndx);
898 mesh1D=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
903 mesh1D=const_cast<MEDCouplingUMesh *>(this);
909 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2,1] !");
912 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=0; revDescIndx=0;
913 mesh1D->getReverseNodalConnectivity(desc,descIndx);
914 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0(DataArrayInt::New());
915 ret0->alloc(desc->getNumberOfTuples(),1);
916 int *r0Pt(ret0->getPointer());
917 const int *c1DPtr(mesh1D->getNodalConnectivity()->begin()),*rn(desc->begin()),*rni(descIndx->begin());
918 for(int i=0;i<nbNodes;i++,rni++)
920 for(const int *oneDCellIt=rn+rni[0];oneDCellIt!=rn+rni[1];oneDCellIt++)
921 *r0Pt++=c1DPtr[3*(*oneDCellIt)+1]==i?c1DPtr[3*(*oneDCellIt)+2]:c1DPtr[3*(*oneDCellIt)+1];
923 neighbors=ret0.retn();
924 neighborsIdx=descIndx.retn();
930 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
931 * For speed reasons no check of this will be done.
933 template<class SonsGenerator>
934 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
936 if(!desc || !descIndx || !revDesc || !revDescIndx)
937 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
938 checkConnectivityFullyDefined();
939 int nbOfCells=getNumberOfCells();
940 int nbOfNodes=getNumberOfNodes();
941 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
942 int *revNodalIndxPtr=revNodalIndx->getPointer();
943 const int *conn=_nodal_connec->getConstPointer();
944 const int *connIndex=_nodal_connec_index->getConstPointer();
945 std::string name="Mesh constituent of "; name+=getName();
946 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA);
947 ret->setCoords(getCoords());
948 ret->allocateCells(2*nbOfCells);
949 descIndx->alloc(nbOfCells+1,1);
950 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
951 int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
952 for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
954 int pos=connIndex[eltId];
955 int posP1=connIndex[eltId+1];
956 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
957 SonsGenerator sg(cm);
958 unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
959 INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
960 for(unsigned i=0;i<nbOfSons;i++)
962 INTERP_KERNEL::NormalizedCellType cmsId;
963 unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
964 for(unsigned k=0;k<nbOfNodesSon;k++)
966 revNodalIndxPtr[tmp[k]+1]++;
967 ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
968 revDesc2->pushBackSilent(eltId);
970 descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
972 int nbOfCellsM1=ret->getNumberOfCells();
973 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
974 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
975 std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
976 int *revNodalPtr=revNodal->getPointer();
977 const int *connM1=ret->getNodalConnectivity()->getConstPointer();
978 const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
979 for(int eltId=0;eltId<nbOfCellsM1;eltId++)
981 const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
982 const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
983 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
984 if(*iter>=0)//for polyhedrons
985 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
988 DataArrayInt *commonCells=0,*commonCellsI=0;
989 FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
990 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
991 const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
992 int newNbOfCellsM1=-1;
993 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
994 commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
995 std::vector<bool> isImpacted(nbOfCellsM1,false);
996 for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
997 for(int work2=work[0];work2!=work[1];work2++)
998 isImpacted[commonCellsPtr[work2]]=true;
999 const int *o2nM1Ptr=o2nM1->getConstPointer();
1000 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
1001 const int *n2oM1Ptr=n2oM1->getConstPointer();
1002 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
1003 ret2->copyTinyInfoFrom(this);
1004 desc->alloc(descIndx->back(),1);
1005 int *descPtr=desc->getPointer();
1006 const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
1007 for(int i=0;i<nbOfCellsM1;i++,descPtr++)
1010 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1013 if(i!=n2oM1Ptr[o2nM1Ptr[i]])
1015 const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
1016 *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
1019 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1022 revDesc->reserve(newNbOfCellsM1);
1023 revDescIndx->alloc(newNbOfCellsM1+1,1);
1024 int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
1025 const int *revDesc2Ptr=revDesc2->getConstPointer();
1026 for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
1028 int oldCellIdM1=n2oM1Ptr[i];
1029 if(!isImpacted[oldCellIdM1])
1031 revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
1032 revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
1036 for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
1037 revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
1038 revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
1046 struct MEDCouplingAccVisit
1048 MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1049 int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1050 int _new_nb_of_nodes;
1056 * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1057 * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1058 * array of cell ids. Pay attention that after conversion all algorithms work slower
1059 * with \a this mesh than before conversion. <br> If an exception is thrown during the
1060 * conversion due presence of invalid ids in the array of cells to convert, as a
1061 * result \a this mesh contains some already converted elements. In this case the 2D
1062 * mesh remains valid but 3D mesh becomes \b inconsistent!
1063 * \warning This method can significantly modify the order of geometric types in \a this,
1064 * hence, to write this mesh to the MED file, its cells must be sorted using
1065 * sortCellsInMEDFileFrmt().
1066 * \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1067 * \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1068 * cellIdsToConvertBg.
1069 * \throw If the coordinates array is not set.
1070 * \throw If the nodal connectivity of cells is node defined.
1071 * \throw If dimension of \a this mesh is not either 2 or 3.
1073 * \if ENABLE_EXAMPLES
1074 * \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1075 * \ref py_mcumesh_convertToPolyTypes "Here is a Python example".
1078 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1080 checkFullyDefined();
1081 int dim=getMeshDimension();
1083 throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1084 int nbOfCells(getNumberOfCells());
1087 const int *connIndex=_nodal_connec_index->getConstPointer();
1088 int *conn=_nodal_connec->getPointer();
1089 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1091 if(*iter>=0 && *iter<nbOfCells)
1093 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1094 if(!cm.isQuadratic())
1095 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1097 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1101 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1102 oss << " in range [0," << nbOfCells << ") !";
1103 throw INTERP_KERNEL::Exception(oss.str().c_str());
1109 int *connIndex(_nodal_connec_index->getPointer());
1110 const int *connOld(_nodal_connec->getConstPointer());
1111 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1112 std::vector<bool> toBeDone(nbOfCells,false);
1113 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1115 if(*iter>=0 && *iter<nbOfCells)
1116 toBeDone[*iter]=true;
1119 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1120 oss << " in range [0," << nbOfCells << ") !";
1121 throw INTERP_KERNEL::Exception(oss.str().c_str());
1124 for(int cellId=0;cellId<nbOfCells;cellId++)
1126 int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1127 int lgthOld(posP1-pos-1);
1128 if(toBeDone[cellId])
1130 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1131 unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1132 int *tmp(new int[nbOfFaces*lgthOld+1]);
1133 int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1134 for(unsigned j=0;j<nbOfFaces;j++)
1136 INTERP_KERNEL::NormalizedCellType type;
1137 unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1141 std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1142 connNew->pushBackValsSilent(tmp,tmp+newLgth);
1143 connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1148 connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1149 connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1152 setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1158 * Converts all cells to either polygons (if \a this is a 2D mesh) or
1159 * polyhedrons (if \a this is a 3D mesh).
1160 * \warning As this method is purely for user-friendliness and no optimization is
1161 * done to avoid construction of a useless vector, this method can be costly
1163 * \throw If the coordinates array is not set.
1164 * \throw If the nodal connectivity of cells is node defined.
1165 * \throw If dimension of \a this mesh is not either 2 or 3.
1167 void MEDCouplingUMesh::convertAllToPoly()
1169 int nbOfCells=getNumberOfCells();
1170 std::vector<int> cellIds(nbOfCells);
1171 for(int i=0;i<nbOfCells;i++)
1173 convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1177 * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1178 * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1179 * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1180 * base facet of the volume and the second half of nodes describes an opposite facet
1181 * having the same number of nodes as the base one. This method converts such
1182 * connectivity to a valid polyhedral format where connectivity of each facet is
1183 * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1184 * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1185 * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1186 * a correct orientation of the first facet of a polyhedron, else orientation of a
1187 * corrected cell is reverse.<br>
1188 * This method is useful to build an extruded unstructured mesh with polyhedrons as
1189 * it releases the user from boring description of polyhedra connectivity in the valid
1191 * \throw If \a this->getMeshDimension() != 3.
1192 * \throw If \a this->getSpaceDimension() != 3.
1193 * \throw If the nodal connectivity of cells is not defined.
1194 * \throw If the coordinates array is not set.
1195 * \throw If \a this mesh contains polyhedrons with the valid connectivity.
1196 * \throw If \a this mesh contains polyhedrons with odd number of nodes.
1198 * \if ENABLE_EXAMPLES
1199 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1200 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1203 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1205 checkFullyDefined();
1206 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1207 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1208 int nbOfCells=getNumberOfCells();
1209 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1210 newCi->alloc(nbOfCells+1,1);
1211 int *newci=newCi->getPointer();
1212 const int *ci=_nodal_connec_index->getConstPointer();
1213 const int *c=_nodal_connec->getConstPointer();
1215 for(int i=0;i<nbOfCells;i++)
1217 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1218 if(type==INTERP_KERNEL::NORM_POLYHED)
1220 if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1222 std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1223 throw INTERP_KERNEL::Exception(oss.str().c_str());
1225 std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1228 std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron with 1 face but there is a mismatch of number of nodes in face should be even !";
1229 throw INTERP_KERNEL::Exception(oss.str().c_str());
1232 newci[i+1]=7*n1+2+newci[i];//6*n1 (nodal length) + n1+2 (number of faces) - 1 (number of '-1' separator is equal to number of faces -1) + 1 (for cell type)
1235 newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1237 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1238 newC->alloc(newci[nbOfCells],1);
1239 int *newc=newC->getPointer();
1240 for(int i=0;i<nbOfCells;i++)
1242 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1243 if(type==INTERP_KERNEL::NORM_POLYHED)
1245 std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1246 newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1248 for(std::size_t j=0;j<n1;j++)
1250 newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1252 newc[n1+5*j+1]=c[ci[i]+1+j];
1253 newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1254 newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1255 newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1260 newc=std::copy(c+ci[i],c+ci[i+1],newc);
1262 _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1263 _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1268 * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1269 * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1270 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1271 * to write this mesh to the MED file, its cells must be sorted using
1272 * sortCellsInMEDFileFrmt().
1273 * \return \c true if at least one cell has been converted, \c false else. In the
1274 * last case the nodal connectivity remains unchanged.
1275 * \throw If the coordinates array is not set.
1276 * \throw If the nodal connectivity of cells is not defined.
1277 * \throw If \a this->getMeshDimension() < 0.
1279 bool MEDCouplingUMesh::unPolyze()
1281 checkFullyDefined();
1282 int mdim=getMeshDimension();
1284 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1287 int nbOfCells=getNumberOfCells();
1290 int initMeshLgth=getMeshLength();
1291 int *conn=_nodal_connec->getPointer();
1292 int *index=_nodal_connec_index->getPointer();
1297 for(int i=0;i<nbOfCells;i++)
1299 lgthOfCurCell=index[i+1]-posOfCurCell;
1300 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1301 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1302 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1306 switch(cm.getDimension())
1310 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1311 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1312 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1317 int nbOfFaces,lgthOfPolyhConn;
1318 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1319 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1324 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1328 ret=ret || (newType!=type);
1329 conn[newPos]=newType;
1331 posOfCurCell=index[i+1];
1336 std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1337 newPos+=lgthOfCurCell;
1338 posOfCurCell+=lgthOfCurCell;
1342 if(newPos!=initMeshLgth)
1343 _nodal_connec->reAlloc(newPos);
1350 * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1351 * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1352 * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells.
1354 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not. This epsilon is used to recenter around origin to have maximal
1357 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1359 checkFullyDefined();
1360 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1361 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1362 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1363 coords->recenterForMaxPrecision(eps);
1365 int nbOfCells=getNumberOfCells();
1366 const int *conn=_nodal_connec->getConstPointer();
1367 const int *index=_nodal_connec_index->getConstPointer();
1368 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1369 connINew->alloc(nbOfCells+1,1);
1370 int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1371 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1373 for(int i=0;i<nbOfCells;i++,connINewPtr++)
1375 if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1377 SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1381 connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1382 *connINewPtr=connNew->getNumberOfTuples();
1385 setConnectivity(connNew,connINew,false);
1389 * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1390 * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1391 * the format of returned DataArrayInt instance.
1393 * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1394 * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1396 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1398 checkConnectivityFullyDefined();
1399 int nbOfCells=getNumberOfCells();
1400 const int *connIndex=_nodal_connec_index->getConstPointer();
1401 const int *conn=_nodal_connec->getConstPointer();
1402 const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1403 int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1404 std::vector<bool> retS(maxElt,false);
1405 for(int i=0;i<nbOfCells;i++)
1406 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1410 for(int i=0;i<maxElt;i++)
1413 DataArrayInt *ret=DataArrayInt::New();
1415 int *retPtr=ret->getPointer();
1416 for(int i=0;i<maxElt;i++)
1423 * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1424 * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1426 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1428 int nbOfNodes((int)nodeIdsInUse.size()),nbOfCells(getNumberOfCells());
1429 const int *connIndex(_nodal_connec_index->getConstPointer()),*conn(_nodal_connec->getConstPointer());
1430 for(int i=0;i<nbOfCells;i++)
1431 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1434 if(conn[j]<nbOfNodes)
1435 nodeIdsInUse[conn[j]]=true;
1438 std::ostringstream oss; oss << "MEDCouplingUMesh::computeNodeIdsAlg : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1439 throw INTERP_KERNEL::Exception(oss.str().c_str());
1445 * Finds nodes not used in any cell and returns an array giving a new id to every node
1446 * by excluding the unused nodes, for which the array holds -1. The result array is
1447 * a mapping in "Old to New" mode.
1448 * \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1449 * \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1450 * this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1451 * if the node is unused or a new id else. The caller is to delete this
1452 * array using decrRef() as it is no more needed.
1453 * \throw If the coordinates array is not set.
1454 * \throw If the nodal connectivity of cells is not defined.
1455 * \throw If the nodal connectivity includes an invalid id.
1457 * \if ENABLE_EXAMPLES
1458 * \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1459 * \ref py_mcumesh_getNodeIdsInUse "Here is a Python example".
1461 * \sa computeFetchedNodeIds, computeNodeIdsAlg()
1463 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1466 int nbOfNodes(getNumberOfNodes());
1467 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1468 ret->alloc(nbOfNodes,1);
1469 int *traducer=ret->getPointer();
1470 std::fill(traducer,traducer+nbOfNodes,-1);
1471 int nbOfCells=getNumberOfCells();
1472 const int *connIndex=_nodal_connec_index->getConstPointer();
1473 const int *conn=_nodal_connec->getConstPointer();
1474 for(int i=0;i<nbOfCells;i++)
1475 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1478 if(conn[j]<nbOfNodes)
1479 traducer[conn[j]]=1;
1482 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1483 throw INTERP_KERNEL::Exception(oss.str().c_str());
1486 nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1487 std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1492 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1493 * For each cell in \b this the number of nodes constituting cell is computed.
1494 * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1495 * So for pohyhedrons some nodes can be counted several times in the returned result.
1497 * \return a newly allocated array
1498 * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1500 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1502 checkConnectivityFullyDefined();
1503 int nbOfCells=getNumberOfCells();
1504 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1505 ret->alloc(nbOfCells,1);
1506 int *retPtr=ret->getPointer();
1507 const int *conn=getNodalConnectivity()->getConstPointer();
1508 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1509 for(int i=0;i<nbOfCells;i++,retPtr++)
1511 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1512 *retPtr=connI[i+1]-connI[i]-1;
1514 *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1520 * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1521 * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1523 * \return DataArrayInt * - new object to be deallocated by the caller.
1524 * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1526 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1528 checkConnectivityFullyDefined();
1529 int nbOfCells=getNumberOfCells();
1530 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1531 ret->alloc(nbOfCells,1);
1532 int *retPtr=ret->getPointer();
1533 const int *conn=getNodalConnectivity()->getConstPointer();
1534 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1535 for(int i=0;i<nbOfCells;i++,retPtr++)
1537 std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1538 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1539 *retPtr=(int)s.size();
1543 *retPtr=(int)s.size();
1550 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1551 * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1553 * \return a newly allocated array
1555 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1557 checkConnectivityFullyDefined();
1558 int nbOfCells=getNumberOfCells();
1559 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1560 ret->alloc(nbOfCells,1);
1561 int *retPtr=ret->getPointer();
1562 const int *conn=getNodalConnectivity()->getConstPointer();
1563 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1564 for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1566 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1567 *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1573 * Removes unused nodes (the node coordinates array is shorten) and returns an array
1574 * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1575 * array mean that the corresponding old node is no more used.
1576 * \return DataArrayInt * - a new instance of DataArrayInt of length \a
1577 * this->getNumberOfNodes() before call of this method. The caller is to
1578 * delete this array using decrRef() as it is no more needed.
1579 * \throw If the coordinates array is not set.
1580 * \throw If the nodal connectivity of cells is not defined.
1581 * \throw If the nodal connectivity includes an invalid id.
1582 * \sa areAllNodesFetched
1584 * \if ENABLE_EXAMPLES
1585 * \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1586 * \ref py_mcumesh_zipCoordsTraducer "Here is a Python example".
1589 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1591 return MEDCouplingPointSet::zipCoordsTraducer();
1595 * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1596 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1598 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1603 return AreCellsEqual0(conn,connI,cell1,cell2);
1605 return AreCellsEqual1(conn,connI,cell1,cell2);
1607 return AreCellsEqual2(conn,connI,cell1,cell2);
1609 return AreCellsEqual3(conn,connI,cell1,cell2);
1611 return AreCellsEqual7(conn,connI,cell1,cell2);
1613 throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1617 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1619 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1621 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1622 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1627 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1629 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1631 int sz=connI[cell1+1]-connI[cell1];
1632 if(sz==connI[cell2+1]-connI[cell2])
1634 if(conn[connI[cell1]]==conn[connI[cell2]])
1636 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1637 unsigned dim=cm.getDimension();
1643 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1644 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1645 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1646 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1647 return work!=tmp+sz1?1:0;
1650 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1653 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1660 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1662 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1664 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1666 if(conn[connI[cell1]]==conn[connI[cell2]])
1668 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1669 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1677 * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1679 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1681 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1683 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1684 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1691 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1693 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1695 int sz=connI[cell1+1]-connI[cell1];
1696 if(sz==connI[cell2+1]-connI[cell2])
1698 if(conn[connI[cell1]]==conn[connI[cell2]])
1700 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1701 unsigned dim=cm.getDimension();
1707 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1708 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1709 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1710 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1715 std::reverse_iterator<int *> it1((int *)tmp+sz1);
1716 std::reverse_iterator<int *> it2((int *)tmp);
1717 if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1723 return work!=tmp+sz1?1:0;
1726 {//case of SEG2 and SEG3
1727 if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1729 if(!cm.isQuadratic())
1731 std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1732 std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1733 if(std::equal(it1,it2,conn+connI[cell2]+1))
1739 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])
1746 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1753 * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1754 * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1755 * and result remains unchanged.
1756 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1757 * If in 'candidates' pool -1 value is considered as an empty value.
1758 * WARNING this method returns only ONE set of result !
1760 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1762 if(candidates.size()<1)
1765 std::vector<int>::const_iterator iter=candidates.begin();
1766 int start=(*iter++);
1767 for(;iter!=candidates.end();iter++)
1769 int status=AreCellsEqual(conn,connI,start,*iter,compType);
1774 result->pushBackSilent(start);
1778 result->pushBackSilent(*iter);
1780 result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1787 * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1788 * This method keeps the coordiantes of \a this. This method is time consuming and is called
1790 * \param [in] compType input specifying the technique used to compare cells each other.
1791 * - 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.
1792 * - 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)
1793 * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1794 * - 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
1795 * can be used for users not sensitive to orientation of cell
1796 * \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.
1797 * \param [out] commonCells
1798 * \param [out] commonCellsI
1799 * \return the correspondance array old to new in a newly allocated array.
1802 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1804 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1805 getReverseNodalConnectivity(revNodal,revNodalI);
1806 FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1809 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1810 DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr)
1812 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1813 int nbOfCells=nodalI->getNumberOfTuples()-1;
1814 commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1815 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1816 const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1817 std::vector<bool> isFetched(nbOfCells,false);
1820 for(int i=0;i<nbOfCells;i++)
1824 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1825 std::vector<int> v,v2;
1826 if(connOfNode!=connPtr+connIPtr[i+1])
1828 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1829 v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1832 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1836 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1837 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1838 v2.resize(std::distance(v2.begin(),it));
1842 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1844 int pos=commonCellsI->back();
1845 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1846 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1847 isFetched[*it]=true;
1855 for(int i=startCellId;i<nbOfCells;i++)
1859 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1860 std::vector<int> v,v2;
1861 if(connOfNode!=connPtr+connIPtr[i+1])
1863 v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1866 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1870 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1871 v2.resize(std::distance(v2.begin(),it));
1875 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1877 int pos=commonCellsI->back();
1878 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1879 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1880 isFetched[*it]=true;
1886 commonCellsArr=commonCells.retn();
1887 commonCellsIArr=commonCellsI.retn();
1891 * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1892 * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1893 * than \a other->getNumberOfCells() in the returned array means that there is no
1894 * corresponding cell in \a this mesh.
1895 * It is expected that \a this and \a other meshes share the same node coordinates
1896 * array, if it is not so an exception is thrown.
1897 * \param [in] other - the mesh to compare with.
1898 * \param [in] compType - specifies a cell comparison technique. For meaning of its
1899 * valid values [0,1,2], see zipConnectivityTraducer().
1900 * \param [out] arr - a new instance of DataArrayInt returning correspondence
1901 * between cells of the two meshes. It contains \a other->getNumberOfCells()
1902 * values. The caller is to delete this array using
1903 * decrRef() as it is no more needed.
1904 * \return bool - \c true if all cells of \a other mesh are present in the \a this
1907 * \if ENABLE_EXAMPLES
1908 * \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1909 * \ref py_mcumesh_areCellsIncludedIn "Here is a Python example".
1911 * \sa checkDeepEquivalOnSameNodesWith()
1912 * \sa checkGeoEquivalWith()
1914 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1916 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1917 int nbOfCells=getNumberOfCells();
1918 static const int possibleCompType[]={0,1,2};
1919 if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1921 std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1922 std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1924 throw INTERP_KERNEL::Exception(oss.str().c_str());
1926 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1927 arr=o2n->substr(nbOfCells);
1928 arr->setName(other->getName());
1930 if(other->getNumberOfCells()==0)
1932 return arr->getMaxValue(tmp)<nbOfCells;
1936 * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1937 * This method tries to determine if \b other is fully included in \b this.
1938 * The main difference is that this method is not expected to throw exception.
1939 * This method has two outputs :
1941 * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1942 * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1944 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1946 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1947 DataArrayInt *commonCells=0,*commonCellsI=0;
1948 int thisNbCells=getNumberOfCells();
1949 mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1950 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1951 const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1952 int otherNbCells=other->getNumberOfCells();
1953 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1954 arr2->alloc(otherNbCells,1);
1955 arr2->fillWithZero();
1956 int *arr2Ptr=arr2->getPointer();
1957 int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1958 for(int i=0;i<nbOfCommon;i++)
1960 int start=commonCellsPtr[commonCellsIPtr[i]];
1961 if(start<thisNbCells)
1963 for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1965 int sig=commonCellsPtr[j]>0?1:-1;
1966 int val=std::abs(commonCellsPtr[j])-1;
1967 if(val>=thisNbCells)
1968 arr2Ptr[val-thisNbCells]=sig*(start+1);
1972 arr2->setName(other->getName());
1973 if(arr2->presenceOfValue(0))
1979 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1982 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1983 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1985 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1986 std::vector<const MEDCouplingUMesh *> ms(2);
1989 return MergeUMeshesOnSameCoords(ms);
1993 * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1994 * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1995 * cellIds is not given explicitely but by a range python like.
1997 * \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.
1998 * \return a newly allocated
2000 * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
2001 * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
2003 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const
2005 if(getMeshDimension()!=-1)
2006 return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
2009 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
2011 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2013 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2015 return const_cast<MEDCouplingUMesh *>(this);
2020 * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
2021 * The result mesh shares or not the node coordinates array with \a this mesh depending
2022 * on \a keepCoords parameter.
2023 * \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
2024 * to write this mesh to the MED file, its cells must be sorted using
2025 * sortCellsInMEDFileFrmt().
2026 * \param [in] begin - an array of cell ids to include to the new mesh.
2027 * \param [in] end - a pointer to last-plus-one-th element of \a begin.
2028 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2029 * array of \a this mesh, else "free" nodes are removed from the result mesh
2030 * by calling zipCoords().
2031 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2032 * to delete this mesh using decrRef() as it is no more needed.
2033 * \throw If the coordinates array is not set.
2034 * \throw If the nodal connectivity of cells is not defined.
2035 * \throw If any cell id in the array \a begin is not valid.
2037 * \if ENABLE_EXAMPLES
2038 * \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
2039 * \ref py_mcumesh_buildPartOfMySelf "Here is a Python example".
2042 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2044 if(getMeshDimension()!=-1)
2045 return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
2049 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2051 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2053 return const_cast<MEDCouplingUMesh *>(this);
2058 * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2060 * 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.
2061 * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2062 * The number of cells of \b this will remain the same with this method.
2064 * \param [in] begin begin of cell ids (included) of cells in this to assign
2065 * \param [in] end end of cell ids (excluded) of cells in this to assign
2066 * \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 ).
2067 * Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2069 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2071 checkConnectivityFullyDefined();
2072 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2073 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2074 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2075 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2077 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2078 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2079 throw INTERP_KERNEL::Exception(oss.str().c_str());
2081 int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2082 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2084 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2085 throw INTERP_KERNEL::Exception(oss.str().c_str());
2087 int nbOfCells=getNumberOfCells();
2088 bool easyAssign=true;
2089 const int *connI=_nodal_connec_index->getConstPointer();
2090 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2091 for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2093 if(*it>=0 && *it<nbOfCells)
2095 easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2099 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2100 throw INTERP_KERNEL::Exception(oss.str().c_str());
2105 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2110 DataArrayInt *arrOut=0,*arrIOut=0;
2111 MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2113 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2114 setConnectivity(arrOut,arrIOut,true);
2118 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2120 checkConnectivityFullyDefined();
2121 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2122 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2123 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2124 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2126 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2127 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2128 throw INTERP_KERNEL::Exception(oss.str().c_str());
2130 int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2131 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2133 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2134 throw INTERP_KERNEL::Exception(oss.str().c_str());
2136 int nbOfCells=getNumberOfCells();
2137 bool easyAssign=true;
2138 const int *connI=_nodal_connec_index->getConstPointer();
2139 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2141 for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2143 if(it>=0 && it<nbOfCells)
2145 easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2149 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2150 throw INTERP_KERNEL::Exception(oss.str().c_str());
2155 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2160 DataArrayInt *arrOut=0,*arrIOut=0;
2161 MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2163 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2164 setConnectivity(arrOut,arrIOut,true);
2169 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2170 * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2171 * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2172 * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2174 * \param [in] begin input start of array of node ids.
2175 * \param [in] end input end of array of node ids.
2176 * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2177 * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2179 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2181 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2182 checkConnectivityFullyDefined();
2184 int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2185 std::vector<bool> fastFinder(sz,false);
2186 for(const int *work=begin;work!=end;work++)
2187 if(*work>=0 && *work<sz)
2188 fastFinder[*work]=true;
2189 int nbOfCells=getNumberOfCells();
2190 const int *conn=getNodalConnectivity()->getConstPointer();
2191 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2192 for(int i=0;i<nbOfCells;i++)
2194 int ref=0,nbOfHit=0;
2195 for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2199 if(fastFinder[*work2])
2202 if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2203 cellIdsKept->pushBackSilent(i);
2205 cellIdsKeptArr=cellIdsKept.retn();
2209 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2210 * this->getMeshDimension(), that bound some cells of \a this mesh.
2211 * The cells of lower dimension to include to the result mesh are selected basing on
2212 * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2213 * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2214 * ==\c false, a cell is copied if any its node is in the array of node ids. The
2215 * created mesh shares the node coordinates array with \a this mesh.
2216 * \param [in] begin - the array of node ids.
2217 * \param [in] end - a pointer to the (last+1)-th element of \a begin.
2218 * \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2219 * array \a begin are added, else cells whose any node is in the
2220 * array \a begin are added.
2221 * \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2222 * to delete this mesh using decrRef() as it is no more needed.
2223 * \throw If the coordinates array is not set.
2224 * \throw If the nodal connectivity of cells is not defined.
2225 * \throw If any node id in \a begin is not valid.
2227 * \if ENABLE_EXAMPLES
2228 * \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2229 * \ref py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2232 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2234 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2235 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2236 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2237 desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2238 return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2242 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2243 * this->getMeshDimension(), which bound only one cell of \a this mesh.
2244 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2245 * array of \a this mesh, else "free" nodes are removed from the result mesh
2246 * by calling zipCoords().
2247 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2248 * to delete this mesh using decrRef() as it is no more needed.
2249 * \throw If the coordinates array is not set.
2250 * \throw If the nodal connectivity of cells is not defined.
2252 * \if ENABLE_EXAMPLES
2253 * \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2254 * \ref py_mcumesh_buildBoundaryMesh "Here is a Python example".
2257 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2259 DataArrayInt *desc=DataArrayInt::New();
2260 DataArrayInt *descIndx=DataArrayInt::New();
2261 DataArrayInt *revDesc=DataArrayInt::New();
2262 DataArrayInt *revDescIndx=DataArrayInt::New();
2264 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2267 descIndx->decrRef();
2268 int nbOfCells=meshDM1->getNumberOfCells();
2269 const int *revDescIndxC=revDescIndx->getConstPointer();
2270 std::vector<int> boundaryCells;
2271 for(int i=0;i<nbOfCells;i++)
2272 if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2273 boundaryCells.push_back(i);
2274 revDescIndx->decrRef();
2275 MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2280 * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2281 * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2282 * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown.
2284 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2286 checkFullyDefined();
2287 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2288 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2289 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2290 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2292 buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2293 desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2295 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2296 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2297 const int *revDescPtr=revDesc->getConstPointer();
2298 const int *revDescIndxPtr=revDescIndx->getConstPointer();
2299 int nbOfCells=getNumberOfCells();
2300 std::vector<bool> ret1(nbOfCells,false);
2302 for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2303 if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2304 { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2306 DataArrayInt *ret2=DataArrayInt::New();
2308 int *ret2Ptr=ret2->getPointer();
2310 for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2313 ret2->setName("BoundaryCells");
2318 * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2319 * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2320 * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2321 * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2323 * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2324 * This method method returns cells ids set s = s1 + s2 where :
2326 * - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2327 * - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2329 * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2330 * are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2332 * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2333 * \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
2334 * cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2336 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2338 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2339 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2340 checkConnectivityFullyDefined();
2341 otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2342 if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2343 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2344 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2345 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2346 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2347 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2348 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2349 const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2350 DataArrayInt *idsOtherInConsti=0;
2351 bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2352 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2354 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2356 for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2357 s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2358 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2359 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2360 DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2361 ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2362 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2363 ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2364 neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2365 RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2366 neighThisPartAuto=0;
2367 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2368 const int li[2]={0,1};
2369 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2370 s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2371 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2374 cellIdsRk0=s0arr.retn();
2375 cellIdsRk1=s_renum1.retn();
2379 * 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
2380 * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2382 * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2384 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2386 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2387 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2388 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2389 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2391 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2392 revDesc=0; desc=0; descIndx=0;
2393 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2394 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2395 return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2399 * Finds nodes lying on the boundary of \a this mesh.
2400 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2401 * nodes. The caller is to delete this array using decrRef() as it is no
2403 * \throw If the coordinates array is not set.
2404 * \throw If the nodal connectivity of cells is node defined.
2406 * \if ENABLE_EXAMPLES
2407 * \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2408 * \ref py_mcumesh_findBoundaryNodes "Here is a Python example".
2411 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2413 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2414 return skin->computeFetchedNodeIds();
2417 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2420 return const_cast<MEDCouplingUMesh *>(this);
2424 * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2425 * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2426 * 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.
2427 * 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.
2428 * 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.
2430 * \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
2431 * parameter is altered during the call.
2432 * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2433 * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2434 * \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.
2436 * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2438 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2439 DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const
2441 checkFullyDefined();
2442 otherDimM1OnSameCoords.checkFullyDefined();
2443 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2444 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2445 if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2446 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2447 DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2448 findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2449 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2450 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2451 s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2452 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2453 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2454 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2455 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2456 cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2458 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2459 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2460 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2461 DataArrayInt *idsTmp=0;
2462 bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2463 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2465 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2466 MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2467 DataArrayInt *tmp0=0,*tmp1=0;
2468 ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2469 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2470 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2471 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2472 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2473 cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2474 cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2476 cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2477 cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2478 nodeIdsToDuplicate=s3.retn();
2482 * This method operates a modification of the connectivity and coords in \b this.
2483 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2484 * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2485 * 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
2486 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2487 * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2489 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2491 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2492 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2494 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2496 int nbOfNodes=getNumberOfNodes();
2497 duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2498 duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2502 * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of
2503 * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range !
2505 * \param [in] offset - specifies the offset to be applied on each element of connectivity.
2507 * \sa renumberNodesInConn
2509 void MEDCouplingUMesh::renumberNodesWithOffsetInConn(int offset)
2511 checkConnectivityFullyDefined();
2512 int *conn(getNodalConnectivity()->getPointer());
2513 const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2514 int nbOfCells(getNumberOfCells());
2515 for(int i=0;i<nbOfCells;i++)
2516 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2518 int& node=conn[iconn];
2519 if(node>=0)//avoid polyhedron separator
2524 _nodal_connec->declareAsNew();
2529 * Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
2530 * of array. This method is dedicated for renumbering from a big set of nodes the a tiny set of nodes which is the case during extraction
2533 void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& newNodeNumbersO2N)
2535 checkConnectivityFullyDefined();
2536 int *conn(getNodalConnectivity()->getPointer());
2537 const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2538 int nbOfCells(getNumberOfCells());
2539 for(int i=0;i<nbOfCells;i++)
2540 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2542 int& node=conn[iconn];
2543 if(node>=0)//avoid polyhedron separator
2545 INTERP_KERNEL::HashMap<int,int>::const_iterator it(newNodeNumbersO2N.find(node));
2546 if(it!=newNodeNumbersO2N.end())
2552 std::ostringstream oss; oss << "MEDCouplingUMesh::renumberNodesInConn(map) : presence in connectivity for cell #" << i << " of node #" << node << " : Not in map !";
2553 throw INTERP_KERNEL::Exception(oss.str().c_str());
2557 _nodal_connec->declareAsNew();
2562 * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2563 * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2564 * This method is a generalization of shiftNodeNumbersInConn().
2565 * \warning This method performs no check of validity of new ids. **Use it with care !**
2566 * \param [in] newNodeNumbersO2N - a permutation array, of length \a
2567 * this->getNumberOfNodes(), in "Old to New" mode.
2568 * See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2569 * \throw If the nodal connectivity of cells is not defined.
2571 * \if ENABLE_EXAMPLES
2572 * \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2573 * \ref py_mcumesh_renumberNodesInConn "Here is a Python example".
2576 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2578 checkConnectivityFullyDefined();
2579 int *conn=getNodalConnectivity()->getPointer();
2580 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2581 int nbOfCells(getNumberOfCells());
2582 for(int i=0;i<nbOfCells;i++)
2583 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2585 int& node=conn[iconn];
2586 if(node>=0)//avoid polyhedron separator
2588 node=newNodeNumbersO2N[node];
2591 _nodal_connec->declareAsNew();
2596 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2597 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2598 * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2600 * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2602 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2604 checkConnectivityFullyDefined();
2605 int *conn=getNodalConnectivity()->getPointer();
2606 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2607 int nbOfCells=getNumberOfCells();
2608 for(int i=0;i<nbOfCells;i++)
2609 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2611 int& node=conn[iconn];
2612 if(node>=0)//avoid polyhedron separator
2617 _nodal_connec->declareAsNew();
2622 * This method operates a modification of the connectivity in \b this.
2623 * 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.
2624 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2625 * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2626 * 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
2627 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2628 * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2630 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2631 * As an another consequense after the call of this method \b this can be transiently non cohrent.
2633 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2634 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2635 * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ).
2637 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2639 checkConnectivityFullyDefined();
2640 std::map<int,int> m;
2642 for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2644 int *conn=getNodalConnectivity()->getPointer();
2645 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2646 int nbOfCells=getNumberOfCells();
2647 for(int i=0;i<nbOfCells;i++)
2648 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2650 int& node=conn[iconn];
2651 if(node>=0)//avoid polyhedron separator
2653 std::map<int,int>::iterator it=m.find(node);
2662 * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2664 * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2665 * After the call of this method the number of cells remains the same as before.
2667 * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2668 * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2669 * be strictly in [0;this->getNumberOfCells()).
2671 * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2672 * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2673 * should be contained in[0;this->getNumberOfCells()).
2675 * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2677 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2679 checkConnectivityFullyDefined();
2680 int nbCells=getNumberOfCells();
2681 const int *array=old2NewBg;
2683 array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2685 const int *conn=_nodal_connec->getConstPointer();
2686 const int *connI=_nodal_connec_index->getConstPointer();
2687 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2688 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2689 const int *n2oPtr=n2o->begin();
2690 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2691 newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2692 newConn->copyStringInfoFrom(*_nodal_connec);
2693 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2694 newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2695 newConnI->copyStringInfoFrom(*_nodal_connec_index);
2697 int *newC=newConn->getPointer();
2698 int *newCI=newConnI->getPointer();
2701 for(int i=0;i<nbCells;i++)
2704 int nbOfElts=connI[pos+1]-connI[pos];
2705 newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2710 setConnectivity(newConn,newConnI);
2712 free(const_cast<int *>(array));
2716 * Finds cells whose bounding boxes intersect a given bounding box.
2717 * \param [in] bbox - an array defining the bounding box via coordinates of its
2718 * extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2720 * \param [in] eps - a factor used to increase size of the bounding box of cell
2721 * before comparing it with \a bbox. This factor is multiplied by the maximal
2722 * extent of the bounding box of cell to produce an addition to this bounding box.
2723 * \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2724 * cells. The caller is to delete this array using decrRef() as it is no more
2726 * \throw If the coordinates array is not set.
2727 * \throw If the nodal connectivity of cells is not defined.
2729 * \if ENABLE_EXAMPLES
2730 * \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2731 * \ref py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2734 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2736 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2737 if(getMeshDimension()==-1)
2739 elems->pushBackSilent(0);
2740 return elems.retn();
2742 int dim=getSpaceDimension();
2743 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2744 const int* conn = getNodalConnectivity()->getConstPointer();
2745 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2746 const double* coords = getCoords()->getConstPointer();
2747 int nbOfCells=getNumberOfCells();
2748 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2750 for (int i=0; i<dim; i++)
2752 elem_bb[i*2]=std::numeric_limits<double>::max();
2753 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2756 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2758 int node= conn[inode];
2759 if(node>=0)//avoid polyhedron separator
2761 for (int idim=0; idim<dim; idim++)
2763 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2765 elem_bb[idim*2] = coords[node*dim+idim] ;
2767 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2769 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2774 if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2775 elems->pushBackSilent(ielem);
2777 return elems.retn();
2781 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2782 * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2783 * added in 'elems' parameter.
2785 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2787 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2788 if(getMeshDimension()==-1)
2790 elems->pushBackSilent(0);
2791 return elems.retn();
2793 int dim=getSpaceDimension();
2794 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2795 const int* conn = getNodalConnectivity()->getConstPointer();
2796 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2797 const double* coords = getCoords()->getConstPointer();
2798 int nbOfCells=getNumberOfCells();
2799 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2801 for (int i=0; i<dim; i++)
2803 elem_bb[i*2]=std::numeric_limits<double>::max();
2804 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2807 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2809 int node= conn[inode];
2810 if(node>=0)//avoid polyhedron separator
2812 for (int idim=0; idim<dim; idim++)
2814 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2816 elem_bb[idim*2] = coords[node*dim+idim] ;
2818 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2820 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2825 if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2826 elems->pushBackSilent(ielem);
2828 return elems.retn();
2832 * Returns a type of a cell by its id.
2833 * \param [in] cellId - the id of the cell of interest.
2834 * \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2835 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2837 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2839 const int *ptI=_nodal_connec_index->getConstPointer();
2840 const int *pt=_nodal_connec->getConstPointer();
2841 if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2842 return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2845 std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2846 throw INTERP_KERNEL::Exception(oss.str().c_str());
2851 * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2852 * This method does not throw exception if geometric type \a type is not in \a this.
2853 * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2854 * The coordinates array is not considered here.
2856 * \param [in] type the geometric type
2857 * \return cell ids in this having geometric type \a type.
2859 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2862 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2864 checkConnectivityFullyDefined();
2865 int nbCells=getNumberOfCells();
2866 int mdim=getMeshDimension();
2867 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2868 if(mdim!=(int)cm.getDimension())
2869 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2870 const int *ptI=_nodal_connec_index->getConstPointer();
2871 const int *pt=_nodal_connec->getConstPointer();
2872 for(int i=0;i<nbCells;i++)
2874 if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2875 ret->pushBackSilent(i);
2881 * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2883 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2885 const int *ptI=_nodal_connec_index->getConstPointer();
2886 const int *pt=_nodal_connec->getConstPointer();
2887 int nbOfCells=getNumberOfCells();
2889 for(int i=0;i<nbOfCells;i++)
2890 if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2896 * Returns the nodal connectivity of a given cell.
2897 * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2898 * all returned node ids can be used in getCoordinatesOfNode().
2899 * \param [in] cellId - an id of the cell of interest.
2900 * \param [in,out] conn - a vector where the node ids are appended. It is not
2901 * cleared before the appending.
2902 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2904 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2906 const int *ptI=_nodal_connec_index->getConstPointer();
2907 const int *pt=_nodal_connec->getConstPointer();
2908 for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2913 std::string MEDCouplingUMesh::simpleRepr() const
2915 static const char msg0[]="No coordinates specified !";
2916 std::ostringstream ret;
2917 ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2918 ret << "Description of mesh : \"" << getDescription() << "\"\n";
2920 double tt=getTime(tmpp1,tmpp2);
2921 ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2922 ret << "Iteration : " << tmpp1 << " Order : " << tmpp2 << "\n";
2924 { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2926 { ret << " Mesh dimension has not been set or is invalid !"; }
2929 const int spaceDim=getSpaceDimension();
2930 ret << spaceDim << "\nInfo attached on space dimension : ";
2931 for(int i=0;i<spaceDim;i++)
2932 ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2936 ret << msg0 << "\n";
2937 ret << "Number of nodes : ";
2939 ret << getNumberOfNodes() << "\n";
2941 ret << msg0 << "\n";
2942 ret << "Number of cells : ";
2943 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2944 ret << getNumberOfCells() << "\n";
2946 ret << "No connectivity specified !" << "\n";
2947 ret << "Cell types present : ";
2948 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2950 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2951 ret << cm.getRepr() << " ";
2957 std::string MEDCouplingUMesh::advancedRepr() const
2959 std::ostringstream ret;
2960 ret << simpleRepr();
2961 ret << "\nCoordinates array : \n___________________\n\n";
2963 _coords->reprWithoutNameStream(ret);
2965 ret << "No array set !\n";
2966 ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2967 reprConnectivityOfThisLL(ret);
2972 * This method returns a C++ code that is a dump of \a this.
2973 * This method will throw if this is not fully defined.
2975 std::string MEDCouplingUMesh::cppRepr() const
2977 static const char coordsName[]="coords";
2978 static const char connName[]="conn";
2979 static const char connIName[]="connI";
2980 checkFullyDefined();
2981 std::ostringstream ret; ret << "// coordinates" << std::endl;
2982 _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2983 _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2984 _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2985 ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2986 ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2987 ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2988 ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2992 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2994 std::ostringstream ret;
2995 reprConnectivityOfThisLL(ret);
3000 * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
3001 * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
3002 * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
3005 * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
3006 * 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
3007 * with number of tuples set to 0, if not the array is taken as this in the returned instance.
3009 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
3011 int mdim=getMeshDimension();
3013 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
3014 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
3015 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
3016 bool needToCpyCT=true;
3019 tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
3027 if(!_nodal_connec_index)
3029 tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
3034 tmp2=_nodal_connec_index;
3037 ret->setConnectivity(tmp1,tmp2,false);
3042 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
3043 ret->setCoords(coords);
3046 ret->setCoords(_coords);
3050 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
3052 if(_nodal_connec!=0 && _nodal_connec_index!=0)
3054 int nbOfCells=getNumberOfCells();
3055 const int *c=_nodal_connec->getConstPointer();
3056 const int *ci=_nodal_connec_index->getConstPointer();
3057 for(int i=0;i<nbOfCells;i++)
3059 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3060 stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3061 std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3066 stream << "Connectivity not defined !\n";
3069 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3071 const int *ptI=_nodal_connec_index->getConstPointer();
3072 const int *pt=_nodal_connec->getConstPointer();
3073 if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3074 return ptI[cellId+1]-ptI[cellId]-1;
3076 return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3080 * Returns types of cells of the specified part of \a this mesh.
3081 * This method avoids computing sub-mesh explicitely to get its types.
3082 * \param [in] begin - an array of cell ids of interest.
3083 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3084 * \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3085 * describing the cell types.
3086 * \throw If the coordinates array is not set.
3087 * \throw If the nodal connectivity of cells is not defined.
3088 * \sa getAllGeoTypes()
3090 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3092 checkFullyDefined();
3093 std::set<INTERP_KERNEL::NormalizedCellType> ret;
3094 const int *conn=_nodal_connec->getConstPointer();
3095 const int *connIndex=_nodal_connec_index->getConstPointer();
3096 for(const int *w=begin;w!=end;w++)
3097 ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3102 * Defines the nodal connectivity using given connectivity arrays. Optionally updates
3103 * a set of types of cells constituting \a this mesh.
3104 * This method is for advanced users having prepared their connectivity before. For
3105 * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3106 * \param [in] conn - the nodal connectivity array.
3107 * \param [in] connIndex - the nodal connectivity index array.
3108 * \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3111 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3113 DataArrayInt::SetArrayIn(conn,_nodal_connec);
3114 DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3115 if(isComputingTypes)
3121 * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
3122 * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3124 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3125 _nodal_connec(0),_nodal_connec_index(0),
3126 _types(other._types)
3128 if(other._nodal_connec)
3129 _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3130 if(other._nodal_connec_index)
3131 _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3134 MEDCouplingUMesh::~MEDCouplingUMesh()
3137 _nodal_connec->decrRef();
3138 if(_nodal_connec_index)
3139 _nodal_connec_index->decrRef();
3143 * Recomputes a set of cell types of \a this mesh. For more info see
3144 * \ref MEDCouplingUMeshNodalConnectivity.
3146 void MEDCouplingUMesh::computeTypes()
3148 if(_nodal_connec && _nodal_connec_index)
3151 const int *conn=_nodal_connec->getConstPointer();
3152 const int *connIndex=_nodal_connec_index->getConstPointer();
3153 int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
3155 for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
3156 _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
3161 * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3163 void MEDCouplingUMesh::checkFullyDefined() const
3165 if(!_nodal_connec_index || !_nodal_connec || !_coords)
3166 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3170 * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3172 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3174 if(!_nodal_connec_index || !_nodal_connec)
3175 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3179 * Returns a number of cells constituting \a this mesh.
3180 * \return int - the number of cells in \a this mesh.
3181 * \throw If the nodal connectivity of cells is not defined.
3183 int MEDCouplingUMesh::getNumberOfCells() const
3185 if(_nodal_connec_index)
3186 return _nodal_connec_index->getNumberOfTuples()-1;
3191 throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3195 * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3196 * mesh. For more info see \ref MEDCouplingMeshesPage.
3197 * \return int - the dimension of \a this mesh.
3198 * \throw If the mesh dimension is not defined using setMeshDimension().
3200 int MEDCouplingUMesh::getMeshDimension() const
3203 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3208 * Returns a length of the nodal connectivity array.
3209 * This method is for test reason. Normally the integer returned is not useable by
3210 * user. For more info see \ref MEDCouplingUMeshNodalConnectivity.
3211 * \return int - the length of the nodal connectivity array.
3213 int MEDCouplingUMesh::getMeshLength() const
3215 return _nodal_connec->getNbOfElems();
3219 * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3221 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3223 MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3224 tinyInfo.push_back(getMeshDimension());
3225 tinyInfo.push_back(getNumberOfCells());
3227 tinyInfo.push_back(getMeshLength());
3229 tinyInfo.push_back(-1);
3233 * First step of unserialization process.
3235 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3237 return tinyInfo[6]<=0;
3241 * Second step of serialization process.
3242 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3244 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3246 MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3248 a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3252 * Third and final step of serialization process.
3254 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3256 MEDCouplingPointSet::serialize(a1,a2);
3257 if(getMeshDimension()>-1)
3259 a1=DataArrayInt::New();
3260 a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3261 int *ptA1=a1->getPointer();
3262 const int *conn=getNodalConnectivity()->getConstPointer();
3263 const int *index=getNodalConnectivityIndex()->getConstPointer();
3264 ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3265 std::copy(conn,conn+getMeshLength(),ptA1);
3272 * Second and final unserialization process.
3273 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3275 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3277 MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3278 setMeshDimension(tinyInfo[5]);
3282 const int *recvBuffer=a1->getConstPointer();
3283 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3284 myConnecIndex->alloc(tinyInfo[6]+1,1);
3285 std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3286 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3287 myConnec->alloc(tinyInfo[7],1);
3288 std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3289 setConnectivity(myConnec, myConnecIndex);
3294 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3295 * CellIds are given using range specified by a start an end and step.
3297 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3299 checkFullyDefined();
3300 int ncell=getNumberOfCells();
3301 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3302 ret->_mesh_dim=_mesh_dim;
3303 ret->setCoords(_coords);
3304 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3305 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3306 int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3308 const int *conn=_nodal_connec->getConstPointer();
3309 const int *connIndex=_nodal_connec_index->getConstPointer();
3310 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3312 if(work>=0 && work<ncell)
3314 newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3318 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3319 throw INTERP_KERNEL::Exception(oss.str().c_str());
3322 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3323 int *newConnPtr=newConn->getPointer();
3324 std::set<INTERP_KERNEL::NormalizedCellType> types;
3326 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3328 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3329 newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3331 ret->setConnectivity(newConn,newConnI,false);
3333 ret->copyTinyInfoFrom(this);
3338 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3339 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3340 * The return newly allocated mesh will share the same coordinates as \a this.
3342 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3344 checkConnectivityFullyDefined();
3345 int ncell=getNumberOfCells();
3346 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3347 ret->_mesh_dim=_mesh_dim;
3348 ret->setCoords(_coords);
3349 std::size_t nbOfElemsRet=std::distance(begin,end);
3350 int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3352 const int *conn=_nodal_connec->getConstPointer();
3353 const int *connIndex=_nodal_connec_index->getConstPointer();
3355 for(const int *work=begin;work!=end;work++,newNbring++)
3357 if(*work>=0 && *work<ncell)
3358 connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3362 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3363 throw INTERP_KERNEL::Exception(oss.str().c_str());
3366 int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3367 int *connRetWork=connRet;
3368 std::set<INTERP_KERNEL::NormalizedCellType> types;
3369 for(const int *work=begin;work!=end;work++)
3371 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3372 connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3374 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3375 connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3376 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3377 connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3378 ret->setConnectivity(connRetArr,connIndexRetArr,false);
3380 ret->copyTinyInfoFrom(this);
3385 * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3387 * For 1D cells, the returned field contains lengths.<br>
3388 * For 2D cells, the returned field contains areas.<br>
3389 * For 3D cells, the returned field contains volumes.
3390 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3391 * orientation, i.e. the volume is always positive.
3392 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3393 * and one time . The caller is to delete this field using decrRef() as it is no
3396 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3398 std::string name="MeasureOfMesh_";
3400 int nbelem=getNumberOfCells();
3401 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3402 field->setName(name);
3403 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3404 array->alloc(nbelem,1);
3405 double *area_vol=array->getPointer();
3406 field->setArray(array) ; array=0;
3407 field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3408 field->synchronizeTimeWithMesh();
3409 if(getMeshDimension()!=-1)
3412 INTERP_KERNEL::NormalizedCellType type;
3413 int dim_space=getSpaceDimension();
3414 const double *coords=getCoords()->getConstPointer();
3415 const int *connec=getNodalConnectivity()->getConstPointer();
3416 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3417 for(int iel=0;iel<nbelem;iel++)
3419 ipt=connec_index[iel];
3420 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3421 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);
3424 std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3428 area_vol[0]=std::numeric_limits<double>::max();
3430 return field.retn();
3434 * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3436 * For 1D cells, the returned array contains lengths.<br>
3437 * For 2D cells, the returned array contains areas.<br>
3438 * For 3D cells, the returned array contains volumes.
3439 * This method avoids building explicitly a part of \a this mesh to perform the work.
3440 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3441 * orientation, i.e. the volume is always positive.
3442 * \param [in] begin - an array of cell ids of interest.
3443 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3444 * \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3445 * delete this array using decrRef() as it is no more needed.
3447 * \if ENABLE_EXAMPLES
3448 * \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3449 * \ref py_mcumesh_getPartMeasureField "Here is a Python example".
3451 * \sa getMeasureField()
3453 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3455 std::string name="PartMeasureOfMesh_";
3457 int nbelem=(int)std::distance(begin,end);
3458 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3459 array->setName(name);
3460 array->alloc(nbelem,1);
3461 double *area_vol=array->getPointer();
3462 if(getMeshDimension()!=-1)
3465 INTERP_KERNEL::NormalizedCellType type;
3466 int dim_space=getSpaceDimension();
3467 const double *coords=getCoords()->getConstPointer();
3468 const int *connec=getNodalConnectivity()->getConstPointer();
3469 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3470 for(const int *iel=begin;iel!=end;iel++)
3472 ipt=connec_index[*iel];
3473 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3474 *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3477 std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3481 area_vol[0]=std::numeric_limits<double>::max();
3483 return array.retn();
3487 * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3488 * \a this one. The returned field contains the dual cell volume for each corresponding
3489 * node in \a this mesh. In other words, the field returns the getMeasureField() of
3490 * the dual mesh in P1 sens of \a this.<br>
3491 * For 1D cells, the returned field contains lengths.<br>
3492 * For 2D cells, the returned field contains areas.<br>
3493 * For 3D cells, the returned field contains volumes.
3494 * This method is useful to check "P1*" conservative interpolators.
3495 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3496 * orientation, i.e. the volume is always positive.
3497 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3498 * nodes and one time. The caller is to delete this array using decrRef() as
3499 * it is no more needed.
3501 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3503 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3504 std::string name="MeasureOnNodeOfMesh_";
3506 int nbNodes=getNumberOfNodes();
3507 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3508 double cst=1./((double)getMeshDimension()+1.);
3509 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3510 array->alloc(nbNodes,1);
3511 double *valsToFill=array->getPointer();
3512 std::fill(valsToFill,valsToFill+nbNodes,0.);
3513 const double *values=tmp->getArray()->getConstPointer();
3514 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3515 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3516 getReverseNodalConnectivity(da,daInd);
3517 const int *daPtr=da->getConstPointer();
3518 const int *daIPtr=daInd->getConstPointer();
3519 for(int i=0;i<nbNodes;i++)
3520 for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3521 valsToFill[i]+=cst*values[*cell];
3523 ret->setArray(array);
3528 * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3529 * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3530 * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3531 * and are normalized.
3532 * <br> \a this can be either
3533 * - a 2D mesh in 2D or 3D space or
3534 * - an 1D mesh in 2D space.
3536 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3537 * cells and one time. The caller is to delete this field using decrRef() as
3538 * it is no more needed.
3539 * \throw If the nodal connectivity of cells is not defined.
3540 * \throw If the coordinates array is not set.
3541 * \throw If the mesh dimension is not set.
3542 * \throw If the mesh and space dimension is not as specified above.
3544 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3546 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3547 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3548 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3549 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3550 int nbOfCells=getNumberOfCells();
3551 int nbComp=getMeshDimension()+1;
3552 array->alloc(nbOfCells,nbComp);
3553 double *vals=array->getPointer();
3554 const int *connI=_nodal_connec_index->getConstPointer();
3555 const int *conn=_nodal_connec->getConstPointer();
3556 const double *coords=_coords->getConstPointer();
3557 if(getMeshDimension()==2)
3559 if(getSpaceDimension()==3)
3561 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3562 const double *locPtr=loc->getConstPointer();
3563 for(int i=0;i<nbOfCells;i++,vals+=3)
3565 int offset=connI[i];
3566 INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3567 double n=INTERP_KERNEL::norm<3>(vals);
3568 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3573 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3574 const double *isAbsPtr=isAbs->getArray()->begin();
3575 for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3576 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3579 else//meshdimension==1
3582 for(int i=0;i<nbOfCells;i++)
3584 int offset=connI[i];
3585 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3586 double n=INTERP_KERNEL::norm<2>(tmp);
3587 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3592 ret->setArray(array);
3594 ret->synchronizeTimeWithSupport();
3599 * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3600 * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3601 * and are normalized.
3602 * <br> \a this can be either
3603 * - a 2D mesh in 2D or 3D space or
3604 * - an 1D mesh in 2D space.
3606 * This method avoids building explicitly a part of \a this mesh to perform the work.
3607 * \param [in] begin - an array of cell ids of interest.
3608 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3609 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3610 * cells and one time. The caller is to delete this field using decrRef() as
3611 * it is no more needed.
3612 * \throw If the nodal connectivity of cells is not defined.
3613 * \throw If the coordinates array is not set.
3614 * \throw If the mesh dimension is not set.
3615 * \throw If the mesh and space dimension is not as specified above.
3616 * \sa buildOrthogonalField()
3618 * \if ENABLE_EXAMPLES
3619 * \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3620 * \ref py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3623 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3625 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3626 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3627 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3628 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3629 std::size_t nbelems=std::distance(begin,end);
3630 int nbComp=getMeshDimension()+1;
3631 array->alloc((int)nbelems,nbComp);
3632 double *vals=array->getPointer();
3633 const int *connI=_nodal_connec_index->getConstPointer();
3634 const int *conn=_nodal_connec->getConstPointer();
3635 const double *coords=_coords->getConstPointer();
3636 if(getMeshDimension()==2)
3638 if(getSpaceDimension()==3)
3640 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3641 const double *locPtr=loc->getConstPointer();
3642 for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3644 int offset=connI[*i];
3645 INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3646 double n=INTERP_KERNEL::norm<3>(vals);
3647 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3652 for(std::size_t i=0;i<nbelems;i++)
3653 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3656 else//meshdimension==1
3659 for(const int *i=begin;i!=end;i++)
3661 int offset=connI[*i];
3662 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3663 double n=INTERP_KERNEL::norm<2>(tmp);
3664 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3669 ret->setArray(array);
3671 ret->synchronizeTimeWithSupport();
3676 * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3677 * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3678 * and are \b not normalized.
3679 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3680 * cells and one time. The caller is to delete this field using decrRef() as
3681 * it is no more needed.
3682 * \throw If the nodal connectivity of cells is not defined.
3683 * \throw If the coordinates array is not set.
3684 * \throw If \a this->getMeshDimension() != 1.
3685 * \throw If \a this mesh includes cells of type other than SEG2.
3687 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3689 if(getMeshDimension()!=1)
3690 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3691 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3692 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3693 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3694 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3695 int nbOfCells=getNumberOfCells();
3696 int spaceDim=getSpaceDimension();
3697 array->alloc(nbOfCells,spaceDim);
3698 double *pt=array->getPointer();
3699 const double *coo=getCoords()->getConstPointer();
3700 std::vector<int> conn;
3702 for(int i=0;i<nbOfCells;i++)
3705 getNodeIdsOfCell(i,conn);
3706 pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3708 ret->setArray(array);
3710 ret->synchronizeTimeWithSupport();
3715 * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3716 * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3717 * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3718 * from. If a result face is shared by two 3D cells, then the face in included twice in
3720 * \param [in] origin - 3 components of a point defining location of the plane.
3721 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3722 * must be greater than 1e-6.
3723 * \param [in] eps - half-thickness of the plane.
3724 * \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3725 * producing correspondent 2D cells. The caller is to delete this array
3726 * using decrRef() as it is no more needed.
3727 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3728 * not share the node coordinates array with \a this mesh. The caller is to
3729 * delete this mesh using decrRef() as it is no more needed.
3730 * \throw If the coordinates array is not set.
3731 * \throw If the nodal connectivity of cells is not defined.
3732 * \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3733 * \throw If magnitude of \a vec is less than 1e-6.
3734 * \throw If the plane does not intersect any 3D cell of \a this mesh.
3735 * \throw If \a this includes quadratic cells.
3737 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3739 checkFullyDefined();
3740 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3741 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3742 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3743 if(candidates->empty())
3744 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3745 std::vector<int> nodes;
3746 DataArrayInt *cellIds1D=0;
3747 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3748 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3749 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3750 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3751 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3752 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3753 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3754 revDesc2=0; revDescIndx2=0;
3755 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3756 revDesc1=0; revDescIndx1=0;
3757 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3758 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3760 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3761 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3763 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3764 std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3765 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3766 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3767 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3768 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3769 connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3770 subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3771 if(cellIds2->empty())
3772 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3773 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3774 ret->setCoords(mDesc1->getCoords());
3775 ret->setConnectivity(conn,connI,true);
3776 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3781 * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3782 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
3783 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3785 * \param [in] origin - 3 components of a point defining location of the plane.
3786 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3787 * must be greater than 1e-6.
3788 * \param [in] eps - half-thickness of the plane.
3789 * \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3790 * producing correspondent segments. The caller is to delete this array
3791 * using decrRef() as it is no more needed.
3792 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3793 * mesh in 3D space. This mesh does not share the node coordinates array with
3794 * \a this mesh. The caller is to delete this mesh using decrRef() as it is
3796 * \throw If the coordinates array is not set.
3797 * \throw If the nodal connectivity of cells is not defined.
3798 * \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3799 * \throw If magnitude of \a vec is less than 1e-6.
3800 * \throw If the plane does not intersect any 2D cell of \a this mesh.
3801 * \throw If \a this includes quadratic cells.
3803 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3805 checkFullyDefined();
3806 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3807 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3808 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3809 if(candidates->empty())
3810 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3811 std::vector<int> nodes;
3812 DataArrayInt *cellIds1D=0;
3813 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3814 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3815 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3816 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3817 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3818 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3819 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3820 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3821 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3823 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3824 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3826 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3827 int ncellsSub=subMesh->getNumberOfCells();
3828 std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3829 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3830 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3831 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3832 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3834 const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3835 const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3836 for(int i=0;i<ncellsSub;i++)
3838 if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3840 if(cut3DSurf[i].first!=-2)
3842 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3843 connI->pushBackSilent(conn->getNumberOfTuples());
3844 cellIds2->pushBackSilent(i);
3848 int cellId3DSurf=cut3DSurf[i].second;
3849 int offset=nodalI[cellId3DSurf]+1;
3850 int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3851 for(int j=0;j<nbOfEdges;j++)
3853 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3854 connI->pushBackSilent(conn->getNumberOfTuples());
3855 cellIds2->pushBackSilent(cellId3DSurf);
3860 if(cellIds2->empty())
3861 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3862 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3863 ret->setCoords(mDesc1->getCoords());
3864 ret->setConnectivity(conn,connI,true);
3865 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3870 * Finds cells whose bounding boxes intersect a given plane.
3871 * \param [in] origin - 3 components of a point defining location of the plane.
3872 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3873 * must be greater than 1e-6.
3874 * \param [in] eps - half-thickness of the plane.
3875 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3876 * cells. The caller is to delete this array using decrRef() as it is no more
3878 * \throw If the coordinates array is not set.
3879 * \throw If the nodal connectivity of cells is not defined.
3880 * \throw If \a this->getSpaceDimension() != 3.
3881 * \throw If magnitude of \a vec is less than 1e-6.
3882 * \sa buildSlice3D()
3884 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3886 checkFullyDefined();
3887 if(getSpaceDimension()!=3)
3888 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3889 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3891 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3893 vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3894 double angle=acos(vec[2]/normm);
3895 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3899 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3900 double normm2(sqrt(vec2[0]*vec2[0]+vec2[1]*vec2[1]+vec2[2]*vec2[2]));
3901 if(normm2/normm>1e-6)
3902 MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3903 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3905 mw->getBoundingBox(bbox);
3906 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3907 cellIds=mw->getCellsInBoundingBox(bbox,eps);
3911 getBoundingBox(bbox);
3912 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3913 cellIds=getCellsInBoundingBox(bbox,eps);
3915 return cellIds.retn();
3919 * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3920 * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3921 * No consideration of coordinate is done by this method.
3922 * 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)
3923 * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3925 bool MEDCouplingUMesh::isContiguous1D() const
3927 if(getMeshDimension()!=1)
3928 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3929 int nbCells=getNumberOfCells();
3931 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3932 const int *connI=_nodal_connec_index->getConstPointer();
3933 const int *conn=_nodal_connec->getConstPointer();
3934 int ref=conn[connI[0]+2];
3935 for(int i=1;i<nbCells;i++)
3937 if(conn[connI[i]+1]!=ref)
3939 ref=conn[connI[i]+2];
3945 * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3946 * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3947 * \param pt reference point of the line
3948 * \param v normalized director vector of the line
3949 * \param eps max precision before throwing an exception
3950 * \param res output of size this->getNumberOfCells
3952 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3954 if(getMeshDimension()!=1)
3955 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3956 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3957 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3958 if(getSpaceDimension()!=3)
3959 throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3960 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3961 const double *fPtr=f->getArray()->getConstPointer();
3963 for(int i=0;i<getNumberOfCells();i++)
3965 const double *tmp1=fPtr+3*i;
3966 tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3967 tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3968 tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3969 double n1=INTERP_KERNEL::norm<3>(tmp);
3970 n1/=INTERP_KERNEL::norm<3>(tmp1);
3972 throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3974 const double *coo=getCoords()->getConstPointer();
3975 for(int i=0;i<getNumberOfNodes();i++)
3977 std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3978 std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3979 res[i]=std::accumulate(tmp,tmp+3,0.);
3984 * 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.
3985 * \a this is expected to be a mesh so that its space dimension is equal to its
3986 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3987 * 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).
3989 * 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
3990 * 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).
3991 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3993 * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3994 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3996 * \param [in] ptBg the start pointer (included) of the coordinates of the point
3997 * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3998 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3999 * \return the positive value of the distance.
4000 * \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
4002 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
4004 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
4006 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4007 if(meshDim!=spaceDim-1)
4008 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
4009 if(meshDim!=2 && meshDim!=1)
4010 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4011 checkFullyDefined();
4012 if((int)std::distance(ptBg,ptEnd)!=spaceDim)
4013 { 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()); }
4014 DataArrayInt *ret1=0;
4015 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
4016 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
4017 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
4018 cellId=*ret1Safe->begin();
4019 return *ret0->begin();
4023 * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
4024 * to \a this and the first \a cellId in \a this corresponding to the returned distance.
4025 * 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
4026 * 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).
4027 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4029 * \a this is expected to be a mesh so that its space dimension is equal to its
4030 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4031 * 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).
4033 * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
4034 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4036 * \param [in] pts the list of points in which each tuple represents a point
4037 * \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.
4038 * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
4039 * \throw if number of components of \a pts is not equal to the space dimension.
4040 * \throw if mesh dimension of \a this is not equal to space dimension - 1.
4041 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
4043 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
4046 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
4047 pts->checkAllocated();
4048 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4049 if(meshDim!=spaceDim-1)
4050 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
4051 if(meshDim!=2 && meshDim!=1)
4052 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
4053 if(pts->getNumberOfComponents()!=spaceDim)
4055 std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
4056 throw INTERP_KERNEL::Exception(oss.str().c_str());
4058 checkFullyDefined();
4059 int nbCells=getNumberOfCells();
4061 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4062 int nbOfPts=pts->getNumberOfTuples();
4063 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4064 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4065 const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4066 double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4067 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4068 const double *bbox(bboxArr->begin());
4073 BBTreeDst<3> myTree(bbox,0,0,nbCells);
4074 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4076 double x=std::numeric_limits<double>::max();
4077 std::vector<int> elems;
4078 myTree.getMinDistanceOfMax(ptsPtr,x);
4079 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4080 DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4086 BBTreeDst<2> myTree(bbox,0,0,nbCells);
4087 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4089 double x=std::numeric_limits<double>::max();
4090 std::vector<int> elems;
4091 myTree.getMinDistanceOfMax(ptsPtr,x);
4092 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4093 DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4098 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4100 cellIds=ret1.retn();
4105 * \param [in] pt the start pointer (included) of the coordinates of the point
4106 * \param [in] cellIdsBg the start pointer (included) of cellIds
4107 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4108 * \param [in] nc nodal connectivity
4109 * \param [in] ncI nodal connectivity index
4110 * \param [in,out] ret0 the min distance between \a this and the external input point
4111 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4112 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4114 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)
4117 ret0=std::numeric_limits<double>::max();
4118 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4120 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4122 case INTERP_KERNEL::NORM_TRI3:
4124 double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4126 { ret0=tmp; cellId=*zeCell; }
4129 case INTERP_KERNEL::NORM_QUAD4:
4130 case INTERP_KERNEL::NORM_POLYGON:
4132 double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4134 { ret0=tmp; cellId=*zeCell; }
4138 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4144 * \param [in] pt the start pointer (included) of the coordinates of the point
4145 * \param [in] cellIdsBg the start pointer (included) of cellIds
4146 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4147 * \param [in] nc nodal connectivity
4148 * \param [in] ncI nodal connectivity index
4149 * \param [in,out] ret0 the min distance between \a this and the external input point
4150 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4151 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4153 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)
4156 ret0=std::numeric_limits<double>::max();
4157 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4159 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4161 case INTERP_KERNEL::NORM_SEG2:
4163 std::size_t uselessEntry=0;
4164 double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4167 { ret0=tmp; cellId=*zeCell; }
4171 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4177 * Finds cells in contact with a ball (i.e. a point with precision).
4178 * 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.
4179 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4181 * \warning This method is suitable if the caller intends to evaluate only one
4182 * point, for more points getCellsContainingPoints() is recommended as it is
4184 * \param [in] pos - array of coordinates of the ball central point.
4185 * \param [in] eps - ball radius.
4186 * \return int - a smallest id of cells being in contact with the ball, -1 in case
4187 * if there are no such cells.
4188 * \throw If the coordinates array is not set.
4189 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4191 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4193 std::vector<int> elts;
4194 getCellsContainingPoint(pos,eps,elts);
4197 return elts.front();
4201 * Finds cells in contact with a ball (i.e. a point with precision).
4202 * 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.
4203 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4204 * \warning This method is suitable if the caller intends to evaluate only one
4205 * point, for more points getCellsContainingPoints() is recommended as it is
4207 * \param [in] pos - array of coordinates of the ball central point.
4208 * \param [in] eps - ball radius.
4209 * \param [out] elts - vector returning ids of the found cells. It is cleared
4210 * before inserting ids.
4211 * \throw If the coordinates array is not set.
4212 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4214 * \if ENABLE_EXAMPLES
4215 * \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4216 * \ref py_mcumesh_getCellsContainingPoint "Here is a Python example".
4219 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4221 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4222 getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4223 elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4228 namespace ParaMEDMEM
4230 template<const int SPACEDIMM>
4234 static const int MY_SPACEDIM=SPACEDIMM;
4235 static const int MY_MESHDIM=8;
4236 typedef int MyConnType;
4237 static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4239 // useless, but for windows compilation ...
4240 const double* getCoordinatesPtr() const { return 0; }
4241 const int* getConnectivityPtr() const { return 0; }
4242 const int* getConnectivityIndexPtr() const { return 0; }
4243 INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4247 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m)
4249 INTERP_KERNEL::Edge *ret(0);
4250 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]));
4251 m[n0]=bg[0]; m[n1]=bg[1];
4254 case INTERP_KERNEL::NORM_SEG2:
4256 ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4259 case INTERP_KERNEL::NORM_SEG3:
4261 INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4262 INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4263 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4264 // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4265 bool colinearity(inters.areColinears());
4266 delete e1; delete e2;
4268 { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4270 { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4274 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4279 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4281 INTERP_KERNEL::Edge *ret=0;
4284 case INTERP_KERNEL::NORM_SEG2:
4286 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4289 case INTERP_KERNEL::NORM_SEG3:
4291 INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4292 INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4293 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4294 // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4295 bool colinearity=inters.areColinears();
4296 delete e1; delete e2;
4298 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4300 ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4301 mapp2[bg[2]].second=false;
4305 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4311 * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4312 * the global mesh 'mDesc'.
4313 * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4314 * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4316 INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4317 std::map<INTERP_KERNEL::Node *,int>& mapp)
4320 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.
4321 const double *coo=mDesc->getCoords()->getConstPointer();
4322 const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4323 const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4325 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4326 s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4327 for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4329 INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4330 mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4332 INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4333 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4335 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4336 ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4338 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4340 if((*it2).second.second)
4341 mapp[(*it2).second.first]=(*it2).first;
4342 ((*it2).second.first)->decrRef();
4347 INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4351 int locId=nodeId-offset2;
4352 return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4356 int locId=nodeId-offset1;
4357 return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4359 return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4363 * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4365 void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4366 const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4367 /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4369 for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4371 int eltId1=abs(*desc1)-1;
4372 for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4374 std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4375 if(it==mappRev.end())
4377 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4388 template<int SPACEDIM>
4389 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4390 double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4392 elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4393 int *eltsIndexPtr(eltsIndex->getPointer());
4394 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4395 const double *bbox(bboxArr->begin());
4396 int nbOfCells=getNumberOfCells();
4397 const int *conn=_nodal_connec->getConstPointer();
4398 const int *connI=_nodal_connec_index->getConstPointer();
4399 double bb[2*SPACEDIM];
4400 BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4401 for(int i=0;i<nbOfPoints;i++)
4403 eltsIndexPtr[i+1]=eltsIndexPtr[i];
4404 for(int j=0;j<SPACEDIM;j++)
4406 bb[2*j]=pos[SPACEDIM*i+j];
4407 bb[2*j+1]=pos[SPACEDIM*i+j];
4409 std::vector<int> candidates;
4410 myTree.getIntersectingElems(bb,candidates);
4411 for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4413 int sz(connI[(*iter)+1]-connI[*iter]-1);
4414 INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4416 if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4417 status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4421 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4422 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4423 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4424 std::vector<INTERP_KERNEL::Node *> nodes(sz);
4425 INTERP_KERNEL::QuadraticPolygon *pol(0);
4426 for(int j=0;j<sz;j++)
4428 int nodeId(conn[connI[*iter]+1+j]);
4429 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4431 if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4432 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4434 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4435 INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4436 double a(0.),b(0.),c(0.);
4437 a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4438 status=pol->isInOrOut2(n);
4439 delete pol; n->decrRef();
4443 eltsIndexPtr[i+1]++;
4444 elts->pushBackSilent(*iter);
4450 * Finds cells in contact with several balls (i.e. points with precision).
4451 * This method is an extension of getCellContainingPoint() and
4452 * getCellsContainingPoint() for the case of multiple points.
4453 * 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.
4454 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4455 * \param [in] pos - an array of coordinates of points in full interlace mode :
4456 * X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4457 * this->getSpaceDimension() * \a nbOfPoints
4458 * \param [in] nbOfPoints - number of points to locate within \a this mesh.
4459 * \param [in] eps - radius of balls (i.e. the precision).
4460 * \param [out] elts - vector returning ids of found cells.
4461 * \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4462 * dividing cell ids in \a elts into groups each referring to one
4463 * point. Its every element (except the last one) is an index pointing to the
4464 * first id of a group of cells. For example cells in contact with the *i*-th
4465 * point are described by following range of indices:
4466 * [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4467 * \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4468 * Number of cells in contact with the *i*-th point is
4469 * \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4470 * \throw If the coordinates array is not set.
4471 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4473 * \if ENABLE_EXAMPLES
4474 * \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4475 * \ref py_mcumesh_getCellsContainingPoints "Here is a Python example".
4478 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4479 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4481 int spaceDim=getSpaceDimension();
4482 int mDim=getMeshDimension();
4487 const double *coords=_coords->getConstPointer();
4488 getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4495 throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4497 else if(spaceDim==2)
4501 const double *coords=_coords->getConstPointer();
4502 getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4505 throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4507 else if(spaceDim==1)
4511 const double *coords=_coords->getConstPointer();
4512 getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4515 throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4518 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4522 * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4523 * least two its edges intersect each other anywhere except their extremities. An
4524 * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4525 * \param [in,out] cells - a vector returning ids of the found cells. It is not
4526 * cleared before filling in.
4527 * \param [in] eps - precision.
4528 * \throw If \a this->getMeshDimension() != 2.
4529 * \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4531 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4533 const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4534 if(getMeshDimension()!=2)
4535 throw INTERP_KERNEL::Exception(msg);
4536 int spaceDim=getSpaceDimension();
4537 if(spaceDim!=2 && spaceDim!=3)
4538 throw INTERP_KERNEL::Exception(msg);
4539 const int *conn=_nodal_connec->getConstPointer();
4540 const int *connI=_nodal_connec_index->getConstPointer();
4541 int nbOfCells=getNumberOfCells();
4542 std::vector<double> cell2DinS2;
4543 for(int i=0;i<nbOfCells;i++)
4545 int offset=connI[i];
4546 int nbOfNodesForCell=connI[i+1]-offset-1;
4547 if(nbOfNodesForCell<=3)
4549 bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4550 project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4551 if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4558 * This method is typically requested to unbutterfly 2D linear cells in \b this.
4560 * 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.
4561 * 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.
4563 * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4564 * This convex envelop is computed using Jarvis march algorithm.
4565 * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4566 * 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)
4567 * 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.
4569 * \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.
4570 * \sa MEDCouplingUMesh::colinearize2D
4572 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4574 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4575 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D works only for meshDim=2 and spaceDim=2 !");
4576 checkFullyDefined();
4577 const double *coords=getCoords()->getConstPointer();
4578 int nbOfCells=getNumberOfCells();
4579 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4580 nodalConnecIndexOut->alloc(nbOfCells+1,1);
4581 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4582 int *workIndexOut=nodalConnecIndexOut->getPointer();
4584 const int *nodalConnecIn=_nodal_connec->getConstPointer();
4585 const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4586 std::set<INTERP_KERNEL::NormalizedCellType> types;
4587 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4588 isChanged->alloc(0,1);
4589 for(int i=0;i<nbOfCells;i++,workIndexOut++)
4591 int pos=nodalConnecOut->getNumberOfTuples();
4592 if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4593 isChanged->pushBackSilent(i);
4594 types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4595 workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4597 if(isChanged->empty())
4599 setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4601 return isChanged.retn();
4605 * This method is \b NOT const because it can modify \a this.
4606 * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4607 * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4608 * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4609 * \b 1 for translation and rotation around point of 'mesh1D'.
4610 * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.
4612 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4614 checkFullyDefined();
4615 mesh1D->checkFullyDefined();
4616 if(!mesh1D->isContiguous1D())
4617 throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4618 if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4619 throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4620 if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4621 throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4622 if(mesh1D->getMeshDimension()!=1)
4623 throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4625 if(isPresenceOfQuadratic())
4627 if(mesh1D->isFullyQuadratic())
4630 throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4632 int oldNbOfNodes(getNumberOfNodes());
4633 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4638 newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4643 newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4647 throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4649 setCoords(newCoords);
4650 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad));
4656 * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4657 * If it is not the case an exception will be thrown.
4658 * This method is non const because the coordinate of \a this can be appended with some new points issued from
4659 * intersection of plane defined by ('origin','vec').
4660 * This method has one in/out parameter : 'cut3DCurve'.
4661 * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4662 * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4663 * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4664 * This method will throw an exception if \a this contains a non linear segment.
4666 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4668 checkFullyDefined();
4669 if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4670 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4671 int ncells=getNumberOfCells();
4672 int nnodes=getNumberOfNodes();
4673 double vec2[3],vec3[3],vec4[3];
4674 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4676 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4677 vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4678 const int *conn=_nodal_connec->getConstPointer();
4679 const int *connI=_nodal_connec_index->getConstPointer();
4680 const double *coo=_coords->getConstPointer();
4681 std::vector<double> addCoo;
4682 for(int i=0;i<ncells;i++)
4684 if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4686 if(cut3DCurve[i]==-2)
4688 int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4689 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];
4690 double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4691 double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4692 if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4694 const double *st2=coo+3*st;
4695 vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4696 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]));
4697 if(pos>eps && pos<1-eps)
4699 int nNode=((int)addCoo.size())/3;
4700 vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4701 addCoo.insert(addCoo.end(),vec4,vec4+3);
4702 cut3DCurve[i]=nnodes+nNode;
4708 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4712 int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4713 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4714 coo2->alloc(newNbOfNodes,3);
4715 double *tmp=coo2->getPointer();
4716 tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4717 std::copy(addCoo.begin(),addCoo.end(),tmp);
4718 DataArrayDouble::SetArrayIn(coo2,_coords);
4723 * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4724 * \param mesh1D is the input 1D mesh used for translation computation.
4725 * \return newCoords new coords filled by this method.
4727 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4729 int oldNbOfNodes=getNumberOfNodes();
4730 int nbOf1DCells=mesh1D->getNumberOfCells();
4731 int spaceDim=getSpaceDimension();
4732 DataArrayDouble *ret=DataArrayDouble::New();
4733 std::vector<bool> isQuads;
4734 int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4735 ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4736 double *retPtr=ret->getPointer();
4737 const double *coords=getCoords()->getConstPointer();
4738 double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4740 std::vector<double> c;
4744 for(int i=0;i<nbOf1DCells;i++)
4747 mesh1D->getNodeIdsOfCell(i,v);
4749 mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4750 mesh1D->getCoordinatesOfNode(v[0],c);
4751 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4752 for(int j=0;j<oldNbOfNodes;j++)
4753 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4757 mesh1D->getCoordinatesOfNode(v[1],c);
4758 mesh1D->getCoordinatesOfNode(v[0],c);
4759 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4760 for(int j=0;j<oldNbOfNodes;j++)
4761 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4764 ret->copyStringInfoFrom(*getCoords());
4769 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4770 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4771 * \return newCoords new coords filled by this method.
4773 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4775 if(mesh1D->getSpaceDimension()==2)
4776 return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4777 if(mesh1D->getSpaceDimension()==3)
4778 return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4779 throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4783 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4784 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4785 * \return newCoords new coords filled by this method.
4787 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4790 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4791 int oldNbOfNodes=getNumberOfNodes();
4792 int nbOf1DCells=mesh1D->getNumberOfCells();
4794 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4795 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4796 int nbOfLevsInVec=nbOf1DCells+1;
4797 ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4798 double *retPtr=ret->getPointer();
4799 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4800 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4801 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4802 tmp->setCoords(tmp2);
4803 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4804 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4805 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4806 for(int i=1;i<nbOfLevsInVec;i++)
4808 const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4809 const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4810 const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4811 const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4812 tmp->translate(vec);
4813 double tmp3[2],radius,alpha,alpha0;
4814 const double *p0=i+1<nbOfLevsInVec?begin:third;
4815 const double *p1=i+1<nbOfLevsInVec?end:begin;
4816 const double *p2=i+1<nbOfLevsInVec?third:end;
4817 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4818 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]);
4819 double angle=acos(cosangle/(radius*radius));
4820 tmp->rotate(end,0,angle);
4821 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4827 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4828 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4829 * \return newCoords new coords filled by this method.
4831 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4834 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4835 int oldNbOfNodes=getNumberOfNodes();
4836 int nbOf1DCells=mesh1D->getNumberOfCells();
4838 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4839 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4840 int nbOfLevsInVec=nbOf1DCells+1;
4841 ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4842 double *retPtr=ret->getPointer();
4843 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4844 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4845 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4846 tmp->setCoords(tmp2);
4847 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4848 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4849 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4850 for(int i=1;i<nbOfLevsInVec;i++)
4852 const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4853 const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4854 const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4855 const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4856 tmp->translate(vec);
4857 double tmp3[2],radius,alpha,alpha0;
4858 const double *p0=i+1<nbOfLevsInVec?begin:third;
4859 const double *p1=i+1<nbOfLevsInVec?end:begin;
4860 const double *p2=i+1<nbOfLevsInVec?third:end;
4861 double vecPlane[3]={
4862 (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4863 (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4864 (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4866 double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4869 vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4870 double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4871 double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4873 double c2=cos(asin(s2));
4875 {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4876 {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4877 {-vec2[1]*s2, vec2[0]*s2, c2}
4879 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]};
4880 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]};
4881 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]};
4882 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4883 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]);
4884 double angle=acos(cosangle/(radius*radius));
4885 tmp->rotate(end,vecPlane,angle);
4887 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4893 * This method is private because not easy to use for end user. This method is const contrary to
4894 * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4895 * the coords sorted slice by slice.
4896 * \param isQuad specifies presence of quadratic cells.
4898 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4900 int nbOf1DCells(getNumberOfNodes()/nbOfNodesOf1Lev-1);
4901 int nbOf2DCells(getNumberOfCells());
4902 int nbOf3DCells(nbOf2DCells*nbOf1DCells);
4903 MEDCouplingUMesh *ret(MEDCouplingUMesh::New("Extruded",getMeshDimension()+1));
4904 const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
4905 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()),newConnI(DataArrayInt::New());
4906 newConnI->alloc(nbOf3DCells+1,1);
4907 int *newConnIPtr(newConnI->getPointer());
4909 std::vector<int> newc;
4910 for(int j=0;j<nbOf2DCells;j++)
4912 AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4913 *newConnIPtr++=(int)newc.size();
4915 newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4916 int *newConnPtr(newConn->getPointer());
4917 int deltaPerLev(isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev);
4918 newConnIPtr=newConnI->getPointer();
4919 for(int iz=0;iz<nbOf1DCells;iz++)
4922 std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4923 const int *posOfTypeOfCell(newConnIPtr);
4924 for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4926 int icell((int)(iter-newc.begin()));//std::distance unfortunately cannot been called here in C++98
4927 if(icell!=*posOfTypeOfCell)
4930 *newConnPtr=(*iter)+iz*deltaPerLev;
4941 ret->setConnectivity(newConn,newConnI,true);
4942 ret->setCoords(getCoords());
4947 * Checks if \a this mesh is constituted by only quadratic cells.
4948 * \return bool - \c true if there are only quadratic cells in \a this mesh.
4949 * \throw If the coordinates array is not set.
4950 * \throw If the nodal connectivity of cells is not defined.
4952 bool MEDCouplingUMesh::isFullyQuadratic() const
4954 checkFullyDefined();
4956 int nbOfCells=getNumberOfCells();
4957 for(int i=0;i<nbOfCells && ret;i++)
4959 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4960 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4961 ret=cm.isQuadratic();
4967 * Checks if \a this mesh includes any quadratic cell.
4968 * \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4969 * \throw If the coordinates array is not set.
4970 * \throw If the nodal connectivity of cells is not defined.
4972 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4974 checkFullyDefined();
4976 int nbOfCells=getNumberOfCells();
4977 for(int i=0;i<nbOfCells && !ret;i++)
4979 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4980 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4981 ret=cm.isQuadratic();
4987 * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4988 * this mesh, it remains unchanged.
4989 * \throw If the coordinates array is not set.
4990 * \throw If the nodal connectivity of cells is not defined.
4992 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4994 checkFullyDefined();
4995 int nbOfCells=getNumberOfCells();
4997 const int *iciptr=_nodal_connec_index->getConstPointer();
4998 for(int i=0;i<nbOfCells;i++)
5000 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5001 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5002 if(cm.isQuadratic())
5004 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5005 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5006 if(!cml.isDynamic())
5007 delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
5009 delta+=(iciptr[i+1]-iciptr[i]-1)/2;
5014 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5015 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5016 const int *icptr=_nodal_connec->getConstPointer();
5017 newConn->alloc(getMeshLength()-delta,1);
5018 newConnI->alloc(nbOfCells+1,1);
5019 int *ocptr=newConn->getPointer();
5020 int *ociptr=newConnI->getPointer();
5023 for(int i=0;i<nbOfCells;i++,ociptr++)
5025 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
5026 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5027 if(!cm.isQuadratic())
5029 _types.insert(type);
5030 ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5031 ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5035 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5036 _types.insert(typel);
5037 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5038 int newNbOfNodes=cml.getNumberOfNodes();
5040 newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
5041 *ocptr++=(int)typel;
5042 ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5043 ociptr[1]=ociptr[0]+newNbOfNodes+1;
5046 setConnectivity(newConn,newConnI,false);
5050 * This method converts all linear cell in \a this to quadratic one.
5051 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5052 * 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)
5053 * 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.
5054 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5055 * end of the existing coordinates.
5057 * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5058 * corresponding quadratic cells. 1 is those creating the 'most' complex.
5059 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5061 * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5063 * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5065 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5067 DataArrayInt *conn=0,*connI=0;
5068 DataArrayDouble *coords=0;
5069 std::set<INTERP_KERNEL::NormalizedCellType> types;
5070 checkFullyDefined();
5071 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5072 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5073 int meshDim=getMeshDimension();
5074 switch(conversionType)
5080 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5081 connSafe=conn; connISafe=connI; coordsSafe=coords;
5084 ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5085 connSafe=conn; connISafe=connI; coordsSafe=coords;
5088 ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5089 connSafe=conn; connISafe=connI; coordsSafe=coords;
5092 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5100 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5101 connSafe=conn; connISafe=connI; coordsSafe=coords;
5104 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5105 connSafe=conn; connISafe=connI; coordsSafe=coords;
5108 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5109 connSafe=conn; connISafe=connI; coordsSafe=coords;
5112 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5117 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5119 setConnectivity(connSafe,connISafe,false);
5121 setCoords(coordsSafe);
5127 * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
5128 * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
5129 * The nodes to be added in those 2D cells are defined by the pair of \a nodeIdsToAdd and \a nodeIdsIndexToAdd.
5130 * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
5131 * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
5132 * This method can be seen as the opposite method of colinearize2D.
5133 * 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
5134 * to avoid to modify the numbering of existing nodes.
5136 * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
5137 * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
5138 * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
5139 * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
5140 * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
5141 * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
5142 * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
5144 * \sa buildDescendingConnectivity2
5146 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
5147 const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
5149 if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
5150 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
5151 nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
5152 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
5153 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
5154 if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
5155 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
5156 //DataArrayInt *out0(0),*outi0(0);
5157 //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
5158 //MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s(out0),outi0s(outi0);
5159 //out0s=out0s->buildUnique(); out0s->sort(true);
5164 * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5165 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5166 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5168 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5170 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5171 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5172 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5173 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5174 int nbOfCells=getNumberOfCells();
5175 int nbOfNodes=getNumberOfNodes();
5176 const int *cPtr=_nodal_connec->getConstPointer();
5177 const int *icPtr=_nodal_connec_index->getConstPointer();
5178 int lastVal=0,offset=nbOfNodes;
5179 for(int i=0;i<nbOfCells;i++,icPtr++)
5181 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5182 if(type==INTERP_KERNEL::NORM_SEG2)
5184 types.insert(INTERP_KERNEL::NORM_SEG3);
5185 newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5186 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5187 newConn->pushBackSilent(offset++);
5189 newConnI->pushBackSilent(lastVal);
5190 ret->pushBackSilent(i);
5195 lastVal+=(icPtr[1]-icPtr[0]);
5196 newConnI->pushBackSilent(lastVal);
5197 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5200 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5201 coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5205 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
5207 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5208 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5209 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5211 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5212 DataArrayInt *conn1D=0,*conn1DI=0;
5213 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5214 DataArrayDouble *coordsTmp=0;
5215 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5216 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5217 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5218 const int *c1DPtr=conn1D->begin();
5219 const int *c1DIPtr=conn1DI->begin();
5220 int nbOfCells=getNumberOfCells();
5221 const int *cPtr=_nodal_connec->getConstPointer();
5222 const int *icPtr=_nodal_connec_index->getConstPointer();
5224 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5226 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5227 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5228 if(!cm.isQuadratic())
5230 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5231 types.insert(typ2); newConn->pushBackSilent(typ2);
5232 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5233 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5234 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5235 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5236 newConnI->pushBackSilent(lastVal);
5237 ret->pushBackSilent(i);
5242 lastVal+=(icPtr[1]-icPtr[0]);
5243 newConnI->pushBackSilent(lastVal);
5244 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5247 conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5252 * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5253 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5254 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5256 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5258 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5259 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5260 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5263 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5265 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5266 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5268 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5269 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5270 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5272 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5273 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5274 DataArrayInt *conn1D=0,*conn1DI=0;
5275 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5276 DataArrayDouble *coordsTmp=0;
5277 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5278 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5279 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5280 const int *c1DPtr=conn1D->begin();
5281 const int *c1DIPtr=conn1DI->begin();
5282 int nbOfCells=getNumberOfCells();
5283 const int *cPtr=_nodal_connec->getConstPointer();
5284 const int *icPtr=_nodal_connec_index->getConstPointer();
5285 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5286 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5288 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5289 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5290 if(!cm.isQuadratic())
5292 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5293 types.insert(typ2); newConn->pushBackSilent(typ2);
5294 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5295 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5296 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5297 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5298 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5299 newConnI->pushBackSilent(lastVal);
5300 ret->pushBackSilent(i);
5305 lastVal+=(icPtr[1]-icPtr[0]);
5306 newConnI->pushBackSilent(lastVal);
5307 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5310 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5311 coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5316 * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5317 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5318 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5320 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5322 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5323 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5324 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5327 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5329 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5330 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5331 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5332 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5334 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5335 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5336 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5338 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5339 const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5340 DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5341 std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5342 DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5343 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5344 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5345 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5346 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5347 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5348 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5349 const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5350 int nbOfCells=getNumberOfCells();
5351 const int *cPtr=_nodal_connec->getConstPointer();
5352 const int *icPtr=_nodal_connec_index->getConstPointer();
5353 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5354 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5356 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5357 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5358 if(!cm.isQuadratic())
5360 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5361 if(typ2==INTERP_KERNEL::NORM_ERROR)
5363 std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5364 throw INTERP_KERNEL::Exception(oss.str().c_str());
5366 types.insert(typ2); newConn->pushBackSilent(typ2);
5367 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5368 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5369 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5370 for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5372 int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5373 int tmpPos=newConn->getNumberOfTuples();
5374 newConn->pushBackSilent(nodeId2);
5375 ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5377 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5378 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5379 newConnI->pushBackSilent(lastVal);
5380 ret->pushBackSilent(i);
5385 lastVal+=(icPtr[1]-icPtr[0]);
5386 newConnI->pushBackSilent(lastVal);
5387 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5390 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5391 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5392 coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5393 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5394 std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5395 int *c=newConn->getPointer();
5396 const int *cI(newConnI->begin());
5397 for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5398 c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5399 offset=coordsTmp2Safe->getNumberOfTuples();
5400 for(const int *elt=ret->begin();elt!=ret->end();elt++)
5401 c[cI[(*elt)+1]-1]+=offset;
5402 coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5407 * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5408 * so that the number of cells remains the same. Quadratic faces are converted to
5409 * polygons. This method works only for 2D meshes in
5410 * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5411 * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5412 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5413 * \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5414 * a polylinized edge constituting the input polygon.
5415 * \throw If the coordinates array is not set.
5416 * \throw If the nodal connectivity of cells is not defined.
5417 * \throw If \a this->getMeshDimension() != 2.
5418 * \throw If \a this->getSpaceDimension() != 2.
5420 void MEDCouplingUMesh::tessellate2D(double eps)
5422 checkFullyDefined();
5423 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
5424 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5425 double epsa=fabs(eps);
5426 if(epsa<std::numeric_limits<double>::min())
5427 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 !");
5428 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5429 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5430 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5431 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5432 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5433 revDesc1=0; revDescIndx1=0;
5434 mDesc->tessellate2DCurve(eps);
5435 subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5436 setCoords(mDesc->getCoords());
5440 * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5441 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5442 * \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5443 * a sub-divided edge.
5444 * \throw If the coordinates array is not set.
5445 * \throw If the nodal connectivity of cells is not defined.
5446 * \throw If \a this->getMeshDimension() != 1.
5447 * \throw If \a this->getSpaceDimension() != 2.
5449 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5451 checkFullyDefined();
5452 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5453 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5454 double epsa=fabs(eps);
5455 if(epsa<std::numeric_limits<double>::min())
5456 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 !");
5457 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5458 int nbCells=getNumberOfCells();
5459 int nbNodes=getNumberOfNodes();
5460 const int *conn=_nodal_connec->getConstPointer();
5461 const int *connI=_nodal_connec_index->getConstPointer();
5462 const double *coords=_coords->getConstPointer();
5463 std::vector<double> addCoo;
5464 std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5465 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5466 newConnI->alloc(nbCells+1,1);
5467 int *newConnIPtr=newConnI->getPointer();
5470 INTERP_KERNEL::Node *tmp2[3];
5471 std::set<INTERP_KERNEL::NormalizedCellType> types;
5472 for(int i=0;i<nbCells;i++,newConnIPtr++)
5474 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5475 if(cm.isQuadratic())
5476 {//assert(connI[i+1]-connI[i]-1==3)
5477 tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5478 tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5479 tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5480 tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5481 INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5484 eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5485 types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5487 newConnIPtr[1]=(int)newConn.size();
5491 types.insert(INTERP_KERNEL::NORM_SEG2);
5492 newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5493 newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5494 newConnIPtr[1]=newConnIPtr[0]+3;
5499 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5500 newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5501 newConnIPtr[1]=newConnIPtr[0]+3;
5504 if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5507 DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5508 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5509 newConnArr->alloc((int)newConn.size(),1);
5510 std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5511 DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5512 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5513 newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5514 double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5515 std::copy(addCoo.begin(),addCoo.end(),work);
5516 DataArrayDouble::SetArrayIn(newCoords,_coords);
5521 * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5522 * In addition, returns an array mapping new cells to old ones. <br>
5523 * This method typically increases the number of cells in \a this mesh
5524 * but the number of nodes remains \b unchanged.
5525 * That's why the 3D splitting policies
5526 * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5527 * \param [in] policy - specifies a pattern used for splitting.
5528 * The semantic of \a policy is:
5529 * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5530 * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5531 * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8 into 5 TETRA4 (for 3D mesh only).
5532 * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8 into 6 TETRA4 (for 3D mesh only).
5533 * \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5534 * an id of old cell producing it. The caller is to delete this array using
5535 * decrRef() as it is no more needed.
5536 * \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5537 * \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5538 * and \a this->getMeshDimension() != 3.
5539 * \throw If \a policy is not one of the four discussed above.
5540 * \throw If the nodal connectivity of cells is not defined.
5541 * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5543 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5548 return simplexizePol0();
5550 return simplexizePol1();
5551 case (int) INTERP_KERNEL::PLANAR_FACE_5:
5552 return simplexizePlanarFace5();
5553 case (int) INTERP_KERNEL::PLANAR_FACE_6:
5554 return simplexizePlanarFace6();
5556 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)");
5561 * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5562 * - 1D: INTERP_KERNEL::NORM_SEG2
5563 * - 2D: INTERP_KERNEL::NORM_TRI3
5564 * - 3D: INTERP_KERNEL::NORM_TETRA4.
5566 * This method is useful for users that need to use P1 field services as
5567 * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5568 * All these methods need mesh support containing only simplex cells.
5569 * \return bool - \c true if there are only simplex cells in \a this mesh.
5570 * \throw If the coordinates array is not set.
5571 * \throw If the nodal connectivity of cells is not defined.
5572 * \throw If \a this->getMeshDimension() < 1.
5574 bool MEDCouplingUMesh::areOnlySimplexCells() const
5576 checkFullyDefined();
5577 int mdim=getMeshDimension();
5578 if(mdim<1 || mdim>3)
5579 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5580 int nbCells=getNumberOfCells();
5581 const int *conn=_nodal_connec->getConstPointer();
5582 const int *connI=_nodal_connec_index->getConstPointer();
5583 for(int i=0;i<nbCells;i++)
5585 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5593 * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5595 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5597 checkConnectivityFullyDefined();
5598 if(getMeshDimension()!=2)
5599 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5600 int nbOfCells=getNumberOfCells();
5601 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5602 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5603 ret->alloc(nbOfCells+nbOfCutCells,1);
5604 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5605 int *retPt=ret->getPointer();
5606 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5607 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5608 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5609 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5610 int *pt=newConn->getPointer();
5611 int *ptI=newConnI->getPointer();
5613 const int *oldc=_nodal_connec->getConstPointer();
5614 const int *ci=_nodal_connec_index->getConstPointer();
5615 for(int i=0;i<nbOfCells;i++,ci++)
5617 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5619 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5620 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5621 pt=std::copy(tmp,tmp+8,pt);
5630 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5631 ptI[1]=ptI[0]+ci[1]-ci[0];
5636 _nodal_connec->decrRef();
5637 _nodal_connec=newConn.retn();
5638 _nodal_connec_index->decrRef();
5639 _nodal_connec_index=newConnI.retn();
5646 * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5648 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5650 checkConnectivityFullyDefined();
5651 if(getMeshDimension()!=2)
5652 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5653 int nbOfCells=getNumberOfCells();
5654 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5655 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5656 ret->alloc(nbOfCells+nbOfCutCells,1);
5657 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5658 int *retPt=ret->getPointer();
5659 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5660 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5661 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5662 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5663 int *pt=newConn->getPointer();
5664 int *ptI=newConnI->getPointer();
5666 const int *oldc=_nodal_connec->getConstPointer();
5667 const int *ci=_nodal_connec_index->getConstPointer();
5668 for(int i=0;i<nbOfCells;i++,ci++)
5670 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5672 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5673 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5674 pt=std::copy(tmp,tmp+8,pt);
5683 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5684 ptI[1]=ptI[0]+ci[1]-ci[0];
5689 _nodal_connec->decrRef();
5690 _nodal_connec=newConn.retn();
5691 _nodal_connec_index->decrRef();
5692 _nodal_connec_index=newConnI.retn();
5699 * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5701 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5703 checkConnectivityFullyDefined();
5704 if(getMeshDimension()!=3)
5705 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5706 int nbOfCells=getNumberOfCells();
5707 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5708 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5709 ret->alloc(nbOfCells+4*nbOfCutCells,1);
5710 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5711 int *retPt=ret->getPointer();
5712 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5713 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5714 newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5715 newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5716 int *pt=newConn->getPointer();
5717 int *ptI=newConnI->getPointer();
5719 const int *oldc=_nodal_connec->getConstPointer();
5720 const int *ci=_nodal_connec_index->getConstPointer();
5721 for(int i=0;i<nbOfCells;i++,ci++)
5723 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5725 for(int j=0;j<5;j++,pt+=5,ptI++)
5727 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5728 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];
5735 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5736 ptI[1]=ptI[0]+ci[1]-ci[0];
5741 _nodal_connec->decrRef();
5742 _nodal_connec=newConn.retn();
5743 _nodal_connec_index->decrRef();
5744 _nodal_connec_index=newConnI.retn();
5751 * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5753 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5755 checkConnectivityFullyDefined();
5756 if(getMeshDimension()!=3)
5757 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5758 int nbOfCells=getNumberOfCells();
5759 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5760 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5761 ret->alloc(nbOfCells+5*nbOfCutCells,1);
5762 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5763 int *retPt=ret->getPointer();
5764 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5765 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5766 newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5767 newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5768 int *pt=newConn->getPointer();
5769 int *ptI=newConnI->getPointer();
5771 const int *oldc=_nodal_connec->getConstPointer();
5772 const int *ci=_nodal_connec_index->getConstPointer();
5773 for(int i=0;i<nbOfCells;i++,ci++)
5775 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5777 for(int j=0;j<6;j++,pt+=5,ptI++)
5779 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5780 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];
5787 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5788 ptI[1]=ptI[0]+ci[1]-ci[0];
5793 _nodal_connec->decrRef();
5794 _nodal_connec=newConn.retn();
5795 _nodal_connec_index->decrRef();
5796 _nodal_connec_index=newConnI.retn();
5803 * 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.
5804 * This method completly ignore coordinates.
5805 * \param nodeSubdived is the nodal connectivity of subdivision of edges
5806 * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5807 * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5808 * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5810 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5812 checkFullyDefined();
5813 if(getMeshDimension()!=2)
5814 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5815 int nbOfCells=getNumberOfCells();
5816 int *connI=_nodal_connec_index->getPointer();
5818 for(int i=0;i<nbOfCells;i++,connI++)
5820 int offset=descIndex[i];
5821 int nbOfEdges=descIndex[i+1]-offset;
5823 bool ddirect=desc[offset+nbOfEdges-1]>0;
5824 int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5825 int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5826 for(int j=0;j<nbOfEdges;j++)
5828 bool direct=desc[offset+j]>0;
5829 int edgeId=std::abs(desc[offset+j])-1;
5830 if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5832 int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5833 int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5834 int ref2=direct?id1:id2;
5837 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5838 newConnLgth+=nbOfSubNodes-1;
5843 std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5844 throw INTERP_KERNEL::Exception(oss.str().c_str());
5849 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5852 newConnLgth++;//+1 is for cell type
5853 connI[1]=newConnLgth;
5856 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5857 newConn->alloc(newConnLgth,1);
5858 int *work=newConn->getPointer();
5859 for(int i=0;i<nbOfCells;i++)
5861 *work++=INTERP_KERNEL::NORM_POLYGON;
5862 int offset=descIndex[i];
5863 int nbOfEdges=descIndex[i+1]-offset;
5864 for(int j=0;j<nbOfEdges;j++)
5866 bool direct=desc[offset+j]>0;
5867 int edgeId=std::abs(desc[offset+j])-1;
5869 work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5872 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5873 std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5874 work=std::copy(it,it+nbOfSubNodes-1,work);
5878 DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5881 _types.insert(INTERP_KERNEL::NORM_POLYGON);
5885 * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5886 * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5887 * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5888 * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5889 * so it can be useful to call mergeNodes() before calling this method.
5890 * \throw If \a this->getMeshDimension() <= 1.
5891 * \throw If the coordinates array is not set.
5892 * \throw If the nodal connectivity of cells is not defined.
5894 void MEDCouplingUMesh::convertDegeneratedCells()
5896 checkFullyDefined();
5897 if(getMeshDimension()<=1)
5898 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5899 int nbOfCells=getNumberOfCells();
5902 int initMeshLgth=getMeshLength();
5903 int *conn=_nodal_connec->getPointer();
5904 int *index=_nodal_connec_index->getPointer();
5908 for(int i=0;i<nbOfCells;i++)
5910 lgthOfCurCell=index[i+1]-posOfCurCell;
5911 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5913 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5914 conn+newPos+1,newLgth);
5915 conn[newPos]=newType;
5917 posOfCurCell=index[i+1];
5920 if(newPos!=initMeshLgth)
5921 _nodal_connec->reAlloc(newPos);
5926 * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5927 * A cell is considered to be oriented correctly if an angle between its
5928 * normal vector and a given vector is less than \c PI / \c 2.
5929 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5931 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5933 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5934 * is not cleared before filling in.
5935 * \throw If \a this->getMeshDimension() != 2.
5936 * \throw If \a this->getSpaceDimension() != 3.
5938 * \if ENABLE_EXAMPLES
5939 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5940 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5943 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
5945 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5946 throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5947 int nbOfCells=getNumberOfCells();
5948 const int *conn=_nodal_connec->getConstPointer();
5949 const int *connI=_nodal_connec_index->getConstPointer();
5950 const double *coordsPtr=_coords->getConstPointer();
5951 for(int i=0;i<nbOfCells;i++)
5953 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5954 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5956 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5957 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5964 * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5965 * considered to be oriented correctly if an angle between its normal vector and a
5966 * given vector is less than \c PI / \c 2.
5967 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5969 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5971 * \throw If \a this->getMeshDimension() != 2.
5972 * \throw If \a this->getSpaceDimension() != 3.
5974 * \if ENABLE_EXAMPLES
5975 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5976 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5979 * \sa changeOrientationOfCells
5981 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
5983 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5984 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5985 int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
5986 const int *connI(_nodal_connec_index->getConstPointer());
5987 const double *coordsPtr(_coords->getConstPointer());
5988 bool isModified(false);
5989 for(int i=0;i<nbOfCells;i++)
5991 INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5992 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5994 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
5995 bool isQuadratic(cm.isQuadratic());
5996 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5999 cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6004 _nodal_connec->declareAsNew();
6009 * This method change the orientation of cells in \a this without any consideration of coordinates. Only connectivity is impacted.
6011 * \sa orientCorrectly2DCells
6013 void MEDCouplingUMesh::changeOrientationOfCells()
6015 int mdim(getMeshDimension());
6016 if(mdim!=2 && mdim!=1)
6017 throw INTERP_KERNEL::Exception("Invalid mesh to apply changeOrientationOfCells on it : must be meshDim==2 or meshDim==1 !");
6018 int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6019 const int *connI(_nodal_connec_index->getConstPointer());
6022 for(int i=0;i<nbOfCells;i++)
6024 INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6025 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6026 cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6031 for(int i=0;i<nbOfCells;i++)
6033 INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6034 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6035 cm.changeOrientationOf1D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6041 * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
6042 * oriented facets. The normal vector of the facet should point out of the cell.
6043 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6044 * is not cleared before filling in.
6045 * \throw If \a this->getMeshDimension() != 3.
6046 * \throw If \a this->getSpaceDimension() != 3.
6047 * \throw If the coordinates array is not set.
6048 * \throw If the nodal connectivity of cells is not defined.
6050 * \if ENABLE_EXAMPLES
6051 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6052 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6055 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
6057 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6058 throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
6059 int nbOfCells=getNumberOfCells();
6060 const int *conn=_nodal_connec->getConstPointer();
6061 const int *connI=_nodal_connec_index->getConstPointer();
6062 const double *coordsPtr=_coords->getConstPointer();
6063 for(int i=0;i<nbOfCells;i++)
6065 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6066 if(type==INTERP_KERNEL::NORM_POLYHED)
6068 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6075 * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6077 * \throw If \a this->getMeshDimension() != 3.
6078 * \throw If \a this->getSpaceDimension() != 3.
6079 * \throw If the coordinates array is not set.
6080 * \throw If the nodal connectivity of cells is not defined.
6081 * \throw If the reparation fails.
6083 * \if ENABLE_EXAMPLES
6084 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6085 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6087 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6089 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
6091 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6092 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6093 int nbOfCells=getNumberOfCells();
6094 int *conn=_nodal_connec->getPointer();
6095 const int *connI=_nodal_connec_index->getConstPointer();
6096 const double *coordsPtr=_coords->getConstPointer();
6097 for(int i=0;i<nbOfCells;i++)
6099 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6100 if(type==INTERP_KERNEL::NORM_POLYHED)
6104 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6105 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6107 catch(INTERP_KERNEL::Exception& e)
6109 std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6110 throw INTERP_KERNEL::Exception(oss.str().c_str());
6118 * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6119 * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6120 * according to which the first facet of the cell should be oriented to have the normal vector
6121 * pointing out of cell.
6122 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6123 * cells. The caller is to delete this array using decrRef() as it is no more
6125 * \throw If \a this->getMeshDimension() != 3.
6126 * \throw If \a this->getSpaceDimension() != 3.
6127 * \throw If the coordinates array is not set.
6128 * \throw If the nodal connectivity of cells is not defined.
6130 * \if ENABLE_EXAMPLES
6131 * \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6132 * \ref py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6134 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6136 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6138 const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6139 if(getMeshDimension()!=3)
6140 throw INTERP_KERNEL::Exception(msg);
6141 int spaceDim=getSpaceDimension();
6143 throw INTERP_KERNEL::Exception(msg);
6145 int nbOfCells=getNumberOfCells();
6146 int *conn=_nodal_connec->getPointer();
6147 const int *connI=_nodal_connec_index->getConstPointer();
6148 const double *coo=getCoords()->getConstPointer();
6149 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6150 for(int i=0;i<nbOfCells;i++)
6152 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6153 if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6155 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6157 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6158 cells->pushBackSilent(i);
6162 return cells.retn();
6166 * This method is a faster method to correct orientation of all 3D cells in \a this.
6167 * 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.
6168 * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6170 * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6171 * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons,
6173 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6175 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6176 throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6177 int nbOfCells=getNumberOfCells();
6178 int *conn=_nodal_connec->getPointer();
6179 const int *connI=_nodal_connec_index->getConstPointer();
6180 const double *coordsPtr=_coords->getConstPointer();
6181 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6182 for(int i=0;i<nbOfCells;i++)
6184 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6187 case INTERP_KERNEL::NORM_TETRA4:
6189 if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6191 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6192 ret->pushBackSilent(i);
6196 case INTERP_KERNEL::NORM_PYRA5:
6198 if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6200 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6201 ret->pushBackSilent(i);
6205 case INTERP_KERNEL::NORM_PENTA6:
6206 case INTERP_KERNEL::NORM_HEXA8:
6207 case INTERP_KERNEL::NORM_HEXGP12:
6209 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6211 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6212 ret->pushBackSilent(i);
6216 case INTERP_KERNEL::NORM_POLYHED:
6218 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6220 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6221 ret->pushBackSilent(i);
6226 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 !");
6234 * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6235 * If it is not the case an exception will be thrown.
6236 * This method is fast because the first cell of \a this is used to compute the plane.
6237 * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6238 * \param pos output of size at least 3 used to store a point owned of searched plane.
6240 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6242 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6243 throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6244 const int *conn=_nodal_connec->getConstPointer();
6245 const int *connI=_nodal_connec_index->getConstPointer();
6246 const double *coordsPtr=_coords->getConstPointer();
6247 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6248 std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6252 * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6253 * cells. Currently cells of the following types are treated:
6254 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6255 * For a cell of other type an exception is thrown.
6256 * Space dimension of a 2D mesh can be either 2 or 3.
6257 * The Edge Ratio of a cell \f$t\f$ is:
6258 * \f$\frac{|t|_\infty}{|t|_0}\f$,
6259 * where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6260 * the smallest edge lengths of \f$t\f$.
6261 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6262 * cells and one time, lying on \a this mesh. The caller is to delete this
6263 * field using decrRef() as it is no more needed.
6264 * \throw If the coordinates array is not set.
6265 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6266 * \throw If the connectivity data array has more than one component.
6267 * \throw If the connectivity data array has a named component.
6268 * \throw If the connectivity index data array has more than one component.
6269 * \throw If the connectivity index data array has a named component.
6270 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6271 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6272 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6274 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6277 int spaceDim=getSpaceDimension();
6278 int meshDim=getMeshDimension();
6279 if(spaceDim!=2 && spaceDim!=3)
6280 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6281 if(meshDim!=2 && meshDim!=3)
6282 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6283 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6285 int nbOfCells=getNumberOfCells();
6286 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6287 arr->alloc(nbOfCells,1);
6288 double *pt=arr->getPointer();
6289 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6290 const int *conn=_nodal_connec->getConstPointer();
6291 const int *connI=_nodal_connec_index->getConstPointer();
6292 const double *coo=_coords->getConstPointer();
6294 for(int i=0;i<nbOfCells;i++,pt++)
6296 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6299 case INTERP_KERNEL::NORM_TRI3:
6301 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6302 *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6305 case INTERP_KERNEL::NORM_QUAD4:
6307 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6308 *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6311 case INTERP_KERNEL::NORM_TETRA4:
6313 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6314 *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6318 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6320 conn+=connI[i+1]-connI[i];
6322 ret->setName("EdgeRatio");
6323 ret->synchronizeTimeWithSupport();
6328 * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6329 * cells. Currently cells of the following types are treated:
6330 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6331 * For a cell of other type an exception is thrown.
6332 * Space dimension of a 2D mesh can be either 2 or 3.
6333 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6334 * cells and one time, lying on \a this mesh. The caller is to delete this
6335 * field using decrRef() as it is no more needed.
6336 * \throw If the coordinates array is not set.
6337 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6338 * \throw If the connectivity data array has more than one component.
6339 * \throw If the connectivity data array has a named component.
6340 * \throw If the connectivity index data array has more than one component.
6341 * \throw If the connectivity index data array has a named component.
6342 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6343 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6344 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6346 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6349 int spaceDim=getSpaceDimension();
6350 int meshDim=getMeshDimension();
6351 if(spaceDim!=2 && spaceDim!=3)
6352 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6353 if(meshDim!=2 && meshDim!=3)
6354 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6355 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6357 int nbOfCells=getNumberOfCells();
6358 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6359 arr->alloc(nbOfCells,1);
6360 double *pt=arr->getPointer();
6361 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6362 const int *conn=_nodal_connec->getConstPointer();
6363 const int *connI=_nodal_connec_index->getConstPointer();
6364 const double *coo=_coords->getConstPointer();
6366 for(int i=0;i<nbOfCells;i++,pt++)
6368 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6371 case INTERP_KERNEL::NORM_TRI3:
6373 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6374 *pt=INTERP_KERNEL::triAspectRatio(tmp);
6377 case INTERP_KERNEL::NORM_QUAD4:
6379 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6380 *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6383 case INTERP_KERNEL::NORM_TETRA4:
6385 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6386 *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6390 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6392 conn+=connI[i+1]-connI[i];
6394 ret->setName("AspectRatio");
6395 ret->synchronizeTimeWithSupport();
6400 * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6401 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6402 * treated: INTERP_KERNEL::NORM_QUAD4.
6403 * For a cell of other type an exception is thrown.
6404 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6405 * cells and one time, lying on \a this mesh. The caller is to delete this
6406 * field using decrRef() as it is no more needed.
6407 * \throw If the coordinates array is not set.
6408 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6409 * \throw If the connectivity data array has more than one component.
6410 * \throw If the connectivity data array has a named component.
6411 * \throw If the connectivity index data array has more than one component.
6412 * \throw If the connectivity index data array has a named component.
6413 * \throw If \a this->getMeshDimension() != 2.
6414 * \throw If \a this->getSpaceDimension() != 3.
6415 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6417 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6420 int spaceDim=getSpaceDimension();
6421 int meshDim=getMeshDimension();
6423 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6425 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6426 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6428 int nbOfCells=getNumberOfCells();
6429 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6430 arr->alloc(nbOfCells,1);
6431 double *pt=arr->getPointer();
6432 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6433 const int *conn=_nodal_connec->getConstPointer();
6434 const int *connI=_nodal_connec_index->getConstPointer();
6435 const double *coo=_coords->getConstPointer();
6437 for(int i=0;i<nbOfCells;i++,pt++)
6439 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6442 case INTERP_KERNEL::NORM_QUAD4:
6444 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6445 *pt=INTERP_KERNEL::quadWarp(tmp);
6449 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6451 conn+=connI[i+1]-connI[i];
6453 ret->setName("Warp");
6454 ret->synchronizeTimeWithSupport();
6460 * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6461 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6462 * treated: INTERP_KERNEL::NORM_QUAD4.
6463 * For a cell of other type an exception is thrown.
6464 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6465 * cells and one time, lying on \a this mesh. The caller is to delete this
6466 * field using decrRef() as it is no more needed.
6467 * \throw If the coordinates array is not set.
6468 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6469 * \throw If the connectivity data array has more than one component.
6470 * \throw If the connectivity data array has a named component.
6471 * \throw If the connectivity index data array has more than one component.
6472 * \throw If the connectivity index data array has a named component.
6473 * \throw If \a this->getMeshDimension() != 2.
6474 * \throw If \a this->getSpaceDimension() != 3.
6475 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6477 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6480 int spaceDim=getSpaceDimension();
6481 int meshDim=getMeshDimension();
6483 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6485 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6486 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6488 int nbOfCells=getNumberOfCells();
6489 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6490 arr->alloc(nbOfCells,1);
6491 double *pt=arr->getPointer();
6492 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6493 const int *conn=_nodal_connec->getConstPointer();
6494 const int *connI=_nodal_connec_index->getConstPointer();
6495 const double *coo=_coords->getConstPointer();
6497 for(int i=0;i<nbOfCells;i++,pt++)
6499 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6502 case INTERP_KERNEL::NORM_QUAD4:
6504 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6505 *pt=INTERP_KERNEL::quadSkew(tmp);
6509 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6511 conn+=connI[i+1]-connI[i];
6513 ret->setName("Skew");
6514 ret->synchronizeTimeWithSupport();
6519 * This method aggregate the bbox of each cell and put it into bbox parameter.
6521 * \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)
6522 * For all other cases this input parameter is ignored.
6523 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6525 * \throw If \a this is not fully set (coordinates and connectivity).
6526 * \throw If a cell in \a this has no valid nodeId.
6527 * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6529 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6531 int mDim(getMeshDimension()),sDim(getSpaceDimension());
6532 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.
6533 return getBoundingBoxForBBTreeFast();
6534 if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6536 bool presenceOfQuadratic(false);
6537 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6539 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6540 if(cm.isQuadratic())
6541 presenceOfQuadratic=true;
6543 if(!presenceOfQuadratic)
6544 return getBoundingBoxForBBTreeFast();
6545 if(mDim==2 && sDim==2)
6546 return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6548 return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6550 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) !");
6554 * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6555 * So meshes having quadratic cells the computed bounding boxes can be invalid !
6557 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6559 * \throw If \a this is not fully set (coordinates and connectivity).
6560 * \throw If a cell in \a this has no valid nodeId.
6562 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6564 checkFullyDefined();
6565 int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6566 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6567 double *bbox(ret->getPointer());
6568 for(int i=0;i<nbOfCells*spaceDim;i++)
6570 bbox[2*i]=std::numeric_limits<double>::max();
6571 bbox[2*i+1]=-std::numeric_limits<double>::max();
6573 const double *coordsPtr(_coords->getConstPointer());
6574 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6575 for(int i=0;i<nbOfCells;i++)
6577 int offset=connI[i]+1;
6578 int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6579 for(int j=0;j<nbOfNodesForCell;j++)
6581 int nodeId=conn[offset+j];
6582 if(nodeId>=0 && nodeId<nbOfNodes)
6584 for(int k=0;k<spaceDim;k++)
6586 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6587 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6594 std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6595 throw INTERP_KERNEL::Exception(oss.str().c_str());
6602 * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6603 * useful for 2D meshes having quadratic cells
6604 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6605 * the two extremities of the arc of circle).
6607 * \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)
6608 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6609 * \throw If \a this is not fully defined.
6610 * \throw If \a this is not a mesh with meshDimension equal to 2.
6611 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6612 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6614 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6616 checkFullyDefined();
6617 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6618 if(spaceDim!=2 || mDim!=2)
6619 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!");
6620 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6621 double *bbox(ret->getPointer());
6622 const double *coords(_coords->getConstPointer());
6623 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6624 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6626 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6627 int sz(connI[1]-connI[0]-1);
6628 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6629 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6630 INTERP_KERNEL::QuadraticPolygon *pol(0);
6631 for(int j=0;j<sz;j++)
6633 int nodeId(conn[*connI+1+j]);
6634 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6636 if(!cm.isQuadratic())
6637 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6639 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6640 INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6641 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax();
6647 * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6648 * useful for 2D meshes having quadratic cells
6649 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6650 * the two extremities of the arc of circle).
6652 * \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)
6653 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6654 * \throw If \a this is not fully defined.
6655 * \throw If \a this is not a mesh with meshDimension equal to 1.
6656 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6657 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6659 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6661 checkFullyDefined();
6662 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6663 if(spaceDim!=2 || mDim!=1)
6664 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!");
6665 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6666 double *bbox(ret->getPointer());
6667 const double *coords(_coords->getConstPointer());
6668 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6669 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6671 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6672 int sz(connI[1]-connI[0]-1);
6673 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6674 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6675 INTERP_KERNEL::Edge *edge(0);
6676 for(int j=0;j<sz;j++)
6678 int nodeId(conn[*connI+1+j]);
6679 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6681 if(!cm.isQuadratic())
6682 edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6684 edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6685 const INTERP_KERNEL::Bounds& b(edge->getBounds());
6686 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6693 namespace ParaMEDMEMImpl
6698 ConnReader(const int *c, int val):_conn(c),_val(val) { }
6699 bool operator() (const int& pos) { return _conn[pos]!=_val; }
6708 ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6709 bool operator() (const int& pos) { return _conn[pos]==_val; }
6719 * This method expects that \a this is sorted by types. If not an exception will be thrown.
6720 * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6721 * \a this is composed in cell types.
6722 * The returned array is of size 3*n where n is the number of different types present in \a this.
6723 * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here.
6724 * This parameter is kept only for compatibility with other methode listed above.
6726 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6728 checkConnectivityFullyDefined();
6729 const int *conn=_nodal_connec->getConstPointer();
6730 const int *connI=_nodal_connec_index->getConstPointer();
6731 const int *work=connI;
6732 int nbOfCells=getNumberOfCells();
6733 std::size_t n=getAllGeoTypes().size();
6734 std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6735 std::set<INTERP_KERNEL::NormalizedCellType> types;
6736 for(std::size_t i=0;work!=connI+nbOfCells;i++)
6738 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6739 if(types.find(typ)!=types.end())
6741 std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6742 oss << " is not contiguous !";
6743 throw INTERP_KERNEL::Exception(oss.str().c_str());
6747 const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6748 ret[3*i+1]=(int)std::distance(work,work2);
6755 * This method is used to check that this has contiguous cell type in same order than described in \a code.
6756 * only for types cell, type node is not managed.
6757 * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6758 * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6759 * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6760 * If 2 or more same geometric type is in \a code and exception is thrown too.
6762 * This method firstly checks
6763 * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6764 * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6765 * an exception is thrown too.
6767 * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6768 * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown
6769 * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6771 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6774 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6775 std::size_t sz=code.size();
6778 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6779 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6781 bool isNoPflUsed=true;
6782 for(std::size_t i=0;i<n;i++)
6783 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6785 types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6787 if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6788 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6789 isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6792 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6795 if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6796 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6797 if(types.size()==_types.size())
6800 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6802 int *retPtr=ret->getPointer();
6803 const int *connI=_nodal_connec_index->getConstPointer();
6804 const int *conn=_nodal_connec->getConstPointer();
6805 int nbOfCells=getNumberOfCells();
6808 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6810 i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6811 int offset=(int)std::distance(connI,i);
6812 const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6813 int nbOfCellsOfCurType=(int)std::distance(i,j);
6814 if(code[3*kk+2]==-1)
6815 for(int k=0;k<nbOfCellsOfCurType;k++)
6819 int idInIdsPerType=code[3*kk+2];
6820 if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6822 const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6825 zePfl->checkAllocated();
6826 if(zePfl->getNumberOfComponents()==1)
6828 for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6830 if(*k>=0 && *k<nbOfCellsOfCurType)
6831 *retPtr=(*k)+offset;
6834 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6835 oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6836 throw INTERP_KERNEL::Exception(oss.str().c_str());
6841 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6844 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6848 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6849 oss << " should be in [0," << idsPerType.size() << ") !";
6850 throw INTERP_KERNEL::Exception(oss.str().c_str());
6859 * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6860 * 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.
6861 * 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.
6862 * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6864 * \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.
6865 * \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,
6866 * \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6867 * \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.
6868 * This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6869 * \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
6871 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6874 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6875 if(profile->getNumberOfComponents()!=1)
6876 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6877 checkConnectivityFullyDefined();
6878 const int *conn=_nodal_connec->getConstPointer();
6879 const int *connI=_nodal_connec_index->getConstPointer();
6880 int nbOfCells=getNumberOfCells();
6881 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6882 std::vector<int> typeRangeVals(1);
6883 for(const int *i=connI;i!=connI+nbOfCells;)
6885 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6886 if(std::find(types.begin(),types.end(),curType)!=types.end())
6888 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6890 types.push_back(curType);
6891 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6892 typeRangeVals.push_back((int)std::distance(connI,i));
6895 DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6896 profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6897 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6898 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6899 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6901 int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6902 code.resize(3*nbOfCastsFinal);
6903 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6904 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6905 for(int i=0;i<nbOfCastsFinal;i++)
6907 int castId=castsPresent->getIJ(i,0);
6908 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6909 idsInPflPerType2.push_back(tmp3);
6910 code[3*i]=(int)types[castId];
6911 code[3*i+1]=tmp3->getNumberOfTuples();
6912 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6913 if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6915 tmp4->copyStringInfoFrom(*profile);
6916 idsPerType2.push_back(tmp4);
6917 code[3*i+2]=(int)idsPerType2.size()-1;
6924 std::size_t sz2=idsInPflPerType2.size();
6925 idsInPflPerType.resize(sz2);
6926 for(std::size_t i=0;i<sz2;i++)
6928 DataArrayInt *locDa=idsInPflPerType2[i];
6930 idsInPflPerType[i]=locDa;
6932 std::size_t sz=idsPerType2.size();
6933 idsPerType.resize(sz);
6934 for(std::size_t i=0;i<sz;i++)
6936 DataArrayInt *locDa=idsPerType2[i];
6938 idsPerType[i]=locDa;
6943 * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6944 * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6945 * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6946 * 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.
6948 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
6950 checkFullyDefined();
6951 nM1LevMesh->checkFullyDefined();
6952 if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6953 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6954 if(_coords!=nM1LevMesh->getCoords())
6955 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6956 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6957 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6958 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6959 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6960 desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6961 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6962 tmp->setConnectivity(tmp0,tmp1);
6963 tmp->renumberCells(ret0->getConstPointer(),false);
6964 revDesc=tmp->getNodalConnectivity();
6965 revDescIndx=tmp->getNodalConnectivityIndex();
6966 DataArrayInt *ret=0;
6967 if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6970 ret->getMaxValue(tmp2);
6972 std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6973 throw INTERP_KERNEL::Exception(oss.str().c_str());
6978 revDescIndx->incrRef();
6981 meshnM1Old2New=ret0;
6986 * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6987 * necessary for writing the mesh to MED file. Additionally returns a permutation array
6988 * in "Old to New" mode.
6989 * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6990 * this array using decrRef() as it is no more needed.
6991 * \throw If the nodal connectivity of cells is not defined.
6993 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
6995 checkConnectivityFullyDefined();
6996 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6997 renumberCells(ret->getConstPointer(),false);
7002 * This methods checks that cells are sorted by their types.
7003 * This method makes asumption (no check) that connectivity is correctly set before calling.
7005 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
7007 checkFullyDefined();
7008 const int *conn=_nodal_connec->getConstPointer();
7009 const int *connI=_nodal_connec_index->getConstPointer();
7010 int nbOfCells=getNumberOfCells();
7011 std::set<INTERP_KERNEL::NormalizedCellType> types;
7012 for(const int *i=connI;i!=connI+nbOfCells;)
7014 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7015 if(types.find(curType)!=types.end())
7017 types.insert(curType);
7018 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7024 * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
7025 * The geometric type order is specified by MED file.
7027 * \sa MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
7029 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
7031 return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7035 * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
7036 * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
7037 * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
7038 * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
7040 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7042 checkFullyDefined();
7043 const int *conn=_nodal_connec->getConstPointer();
7044 const int *connI=_nodal_connec_index->getConstPointer();
7045 int nbOfCells=getNumberOfCells();
7049 std::set<INTERP_KERNEL::NormalizedCellType> sg;
7050 for(const int *i=connI;i!=connI+nbOfCells;)
7052 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7053 const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
7054 if(isTypeExists!=orderEnd)
7056 int pos=(int)std::distance(orderBg,isTypeExists);
7060 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7064 if(sg.find(curType)==sg.end())
7066 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7077 * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
7078 * 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
7079 * 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'.
7081 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
7083 checkConnectivityFullyDefined();
7084 int nbOfCells=getNumberOfCells();
7085 const int *conn=_nodal_connec->getConstPointer();
7086 const int *connI=_nodal_connec_index->getConstPointer();
7087 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
7088 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
7089 tmpa->alloc(nbOfCells,1);
7090 tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
7091 tmpb->fillWithZero();
7092 int *tmp=tmpa->getPointer();
7093 int *tmp2=tmpb->getPointer();
7094 for(const int *i=connI;i!=connI+nbOfCells;i++)
7096 const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
7099 int pos=(int)std::distance(orderBg,where);
7101 tmp[std::distance(connI,i)]=pos;
7105 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
7106 std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
7107 oss << " has a type " << cm.getRepr() << " not in input array of type !";
7108 throw INTERP_KERNEL::Exception(oss.str().c_str());
7111 nbPerType=tmpb.retn();
7116 * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7118 * \return a new object containing the old to new correspondance.
7120 * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7122 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7124 return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7128 * 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.
7129 * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7130 * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7131 * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7133 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7135 DataArrayInt *nbPerType=0;
7136 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7137 nbPerType->decrRef();
7138 return tmpa->buildPermArrPerLevel();
7142 * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7143 * The number of cells remains unchanged after the call of this method.
7144 * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7145 * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7147 * \return the array giving the correspondance old to new.
7149 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7151 checkFullyDefined();
7153 const int *conn=_nodal_connec->getConstPointer();
7154 const int *connI=_nodal_connec_index->getConstPointer();
7155 int nbOfCells=getNumberOfCells();
7156 std::vector<INTERP_KERNEL::NormalizedCellType> types;
7157 for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7158 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7160 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7161 types.push_back(curType);
7162 for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7164 DataArrayInt *ret=DataArrayInt::New();
7165 ret->alloc(nbOfCells,1);
7166 int *retPtr=ret->getPointer();
7167 std::fill(retPtr,retPtr+nbOfCells,-1);
7169 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7171 for(const int *i=connI;i!=connI+nbOfCells;i++)
7172 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7173 retPtr[std::distance(connI,i)]=newCellId++;
7175 renumberCells(retPtr,false);
7180 * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7181 * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7182 * This method makes asumption that connectivity is correctly set before calling.
7184 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7186 checkConnectivityFullyDefined();
7187 const int *conn=_nodal_connec->getConstPointer();
7188 const int *connI=_nodal_connec_index->getConstPointer();
7189 int nbOfCells=getNumberOfCells();
7190 std::vector<MEDCouplingUMesh *> ret;
7191 for(const int *i=connI;i!=connI+nbOfCells;)
7193 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7194 int beginCellId=(int)std::distance(connI,i);
7195 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7196 int endCellId=(int)std::distance(connI,i);
7197 int sz=endCellId-beginCellId;
7198 int *cells=new int[sz];
7199 for(int j=0;j<sz;j++)
7200 cells[j]=beginCellId+j;
7201 MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7209 * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7210 * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7211 * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7213 * \return a newly allocated instance, that the caller must manage.
7214 * \throw If \a this contains more than one geometric type.
7215 * \throw If the nodal connectivity of \a this is not fully defined.
7216 * \throw If the internal data is not coherent.
7218 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7220 checkConnectivityFullyDefined();
7221 if(_types.size()!=1)
7222 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7223 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7224 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7225 ret->setCoords(getCoords());
7226 MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7229 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7230 retC->setNodalConnectivity(c);
7234 MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7236 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7237 DataArrayInt *c=0,*ci=0;
7238 convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7239 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7240 retD->setNodalConnectivity(cs,cis);
7245 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7247 checkConnectivityFullyDefined();
7248 if(_types.size()!=1)
7249 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7250 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7251 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7254 std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7255 oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7256 throw INTERP_KERNEL::Exception(oss.str().c_str());
7258 int nbCells=getNumberOfCells();
7260 int nbNodesPerCell=(int)cm.getNumberOfNodes();
7261 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7262 int *outPtr=connOut->getPointer();
7263 const int *conn=_nodal_connec->begin();
7264 const int *connI=_nodal_connec_index->begin();
7266 for(int i=0;i<nbCells;i++,connI++)
7268 if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7269 outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7272 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 << ") !";
7273 throw INTERP_KERNEL::Exception(oss.str().c_str());
7276 return connOut.retn();
7279 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7281 static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7282 checkConnectivityFullyDefined();
7283 if(_types.size()!=1)
7284 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7285 int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7287 throw INTERP_KERNEL::Exception(msg0);
7288 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7289 c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7290 int *cp(c->getPointer()),*cip(ci->getPointer());
7291 const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7293 for(int i=0;i<nbCells;i++,cip++,incip++)
7295 int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7296 int delta(stop-strt);
7299 if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7300 cp=std::copy(incp+strt,incp+stop,cp);
7302 throw INTERP_KERNEL::Exception(msg0);
7305 throw INTERP_KERNEL::Exception(msg0);
7306 cip[1]=cip[0]+delta;
7308 nodalConn=c.retn(); nodalConnIndex=ci.retn();
7312 * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7313 * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7314 * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7315 * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7316 * are not used here to avoid the build of big permutation array.
7318 * \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
7319 * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7320 * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7321 * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7322 * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7323 * output array gives for each chunck of same type the corresponding mesh id in \b ms.
7324 * \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
7325 * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7327 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7328 DataArrayInt *&szOfCellGrpOfSameType,
7329 DataArrayInt *&idInMsOfCellGrpOfSameType)
7331 std::vector<const MEDCouplingUMesh *> ms2;
7332 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7335 (*it)->checkConnectivityFullyDefined();
7339 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7340 const DataArrayDouble *refCoo=ms2[0]->getCoords();
7341 int meshDim=ms2[0]->getMeshDimension();
7342 std::vector<const MEDCouplingUMesh *> m1ssm;
7343 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7345 std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7346 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7348 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7349 ret1->alloc(0,1); ret2->alloc(0,1);
7350 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7352 if(meshDim!=(*it)->getMeshDimension())
7353 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7354 if(refCoo!=(*it)->getCoords())
7355 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7356 std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7357 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7358 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7359 for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7361 MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7362 m1ssmSingleAuto.push_back(singleCell);
7363 m1ssmSingle.push_back(singleCell);
7364 ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7367 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7368 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7369 std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7370 for(std::size_t i=0;i<m1ssm.size();i++)
7371 m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7372 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7373 szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7374 idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7379 * This method returns a newly created DataArrayInt instance.
7380 * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7382 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7384 checkFullyDefined();
7385 const int *conn=_nodal_connec->getConstPointer();
7386 const int *connIndex=_nodal_connec_index->getConstPointer();
7387 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7388 for(const int *w=begin;w!=end;w++)
7389 if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7390 ret->pushBackSilent(*w);
7395 * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7396 * are in [0:getNumberOfCells())
7398 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7400 checkFullyDefined();
7401 const int *conn=_nodal_connec->getConstPointer();
7402 const int *connI=_nodal_connec_index->getConstPointer();
7403 int nbOfCells=getNumberOfCells();
7404 std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7405 int *tmp=new int[nbOfCells];
7406 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7409 for(const int *i=connI;i!=connI+nbOfCells;i++)
7410 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7411 tmp[std::distance(connI,i)]=j++;
7413 DataArrayInt *ret=DataArrayInt::New();
7414 ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7415 ret->copyStringInfoFrom(*da);
7416 int *retPtr=ret->getPointer();
7417 const int *daPtr=da->getConstPointer();
7418 int nbOfElems=da->getNbOfElems();
7419 for(int k=0;k<nbOfElems;k++)
7420 retPtr[k]=tmp[daPtr[k]];
7426 * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7427 * This method \b works \b for mesh sorted by type.
7428 * cells whose ids is in 'idsPerGeoType' array.
7429 * This method conserves coords and name of mesh.
7431 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7433 std::vector<int> code=getDistributionOfTypes();
7434 std::size_t nOfTypesInThis=code.size()/3;
7435 int sz=0,szOfType=0;
7436 for(std::size_t i=0;i<nOfTypesInThis;i++)
7441 szOfType=code[3*i+1];
7443 for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7444 if(*work<0 || *work>=szOfType)
7446 std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7447 oss << ". It should be in [0," << szOfType << ") !";
7448 throw INTERP_KERNEL::Exception(oss.str().c_str());
7450 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7451 int *idsPtr=idsTokeep->getPointer();
7453 for(std::size_t i=0;i<nOfTypesInThis;i++)
7456 for(int j=0;j<code[3*i+1];j++)
7459 idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7460 offset+=code[3*i+1];
7462 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7463 ret->copyTinyInfoFrom(this);
7468 * This method returns a vector of size 'this->getNumberOfCells()'.
7469 * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7471 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7473 int ncell=getNumberOfCells();
7474 std::vector<bool> ret(ncell);
7475 const int *cI=getNodalConnectivityIndex()->getConstPointer();
7476 const int *c=getNodalConnectivity()->getConstPointer();
7477 for(int i=0;i<ncell;i++)
7479 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7480 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7481 ret[i]=cm.isQuadratic();
7487 * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7489 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7491 if(other->getType()!=UNSTRUCTURED)
7492 throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7493 const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7494 return MergeUMeshes(this,otherC);
7498 * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7499 * computed by averaging coordinates of cell nodes, so this method is not a right
7500 * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7501 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7502 * this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7503 * components. The caller is to delete this array using decrRef() as it is
7505 * \throw If the coordinates array is not set.
7506 * \throw If the nodal connectivity of cells is not defined.
7507 * \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7509 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7511 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7512 int spaceDim=getSpaceDimension();
7513 int nbOfCells=getNumberOfCells();
7514 ret->alloc(nbOfCells,spaceDim);
7515 ret->copyStringInfoFrom(*getCoords());
7516 double *ptToFill=ret->getPointer();
7517 const int *nodal=_nodal_connec->getConstPointer();
7518 const int *nodalI=_nodal_connec_index->getConstPointer();
7519 const double *coor=_coords->getConstPointer();
7520 for(int i=0;i<nbOfCells;i++)
7522 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7523 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7530 * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7531 * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the
7533 * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned
7534 * DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7536 * \sa MEDCouplingUMesh::getBarycenterAndOwner
7537 * \throw If \a this is not fully defined (coordinates and connectivity)
7538 * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7540 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7542 checkFullyDefined();
7543 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7544 int spaceDim=getSpaceDimension();
7545 int nbOfCells=getNumberOfCells();
7546 int nbOfNodes=getNumberOfNodes();
7547 ret->alloc(nbOfCells,spaceDim);
7548 double *ptToFill=ret->getPointer();
7549 const int *nodal=_nodal_connec->getConstPointer();
7550 const int *nodalI=_nodal_connec_index->getConstPointer();
7551 const double *coor=_coords->getConstPointer();
7552 for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7554 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7555 std::fill(ptToFill,ptToFill+spaceDim,0.);
7556 if(type!=INTERP_KERNEL::NORM_POLYHED)
7558 for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7560 if(*conn>=0 && *conn<nbOfNodes)
7561 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7564 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," << nbOfNodes << ") !";
7565 throw INTERP_KERNEL::Exception(oss.str().c_str());
7568 int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7569 if(nbOfNodesInCell>0)
7570 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7573 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7574 throw INTERP_KERNEL::Exception(oss.str().c_str());
7579 std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7581 for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7583 if(*it>=0 && *it<nbOfNodes)
7584 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7587 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," << nbOfNodes << ") !";
7588 throw INTERP_KERNEL::Exception(oss.str().c_str());
7592 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7595 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7596 throw INTERP_KERNEL::Exception(oss.str().c_str());
7604 * Returns a new DataArrayDouble holding barycenters of specified cells. The
7605 * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7606 * are specified via an array of cell ids.
7607 * \warning Validity of the specified cell ids is not checked!
7608 * Valid range is [ 0, \a this->getNumberOfCells() ).
7609 * \param [in] begin - an array of cell ids of interest.
7610 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7611 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7612 * end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7613 * caller is to delete this array using decrRef() as it is no more needed.
7614 * \throw If the coordinates array is not set.
7615 * \throw If the nodal connectivity of cells is not defined.
7617 * \if ENABLE_EXAMPLES
7618 * \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7619 * \ref py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7622 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7624 DataArrayDouble *ret=DataArrayDouble::New();
7625 int spaceDim=getSpaceDimension();
7626 int nbOfTuple=(int)std::distance(begin,end);
7627 ret->alloc(nbOfTuple,spaceDim);
7628 double *ptToFill=ret->getPointer();
7629 double *tmp=new double[spaceDim];
7630 const int *nodal=_nodal_connec->getConstPointer();
7631 const int *nodalI=_nodal_connec_index->getConstPointer();
7632 const double *coor=_coords->getConstPointer();
7633 for(const int *w=begin;w!=end;w++)
7635 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7636 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7644 * 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".
7645 * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7646 * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7647 * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7648 * This method is useful to detect 2D cells in 3D space that are not coplanar.
7650 * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7651 * \throw If spaceDim!=3 or meshDim!=2.
7652 * \throw If connectivity of \a this is invalid.
7653 * \throw If connectivity of a cell in \a this points to an invalid node.
7655 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7657 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7658 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7659 if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7660 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7661 ret->alloc(nbOfCells,4);
7662 double *retPtr(ret->getPointer());
7663 const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7664 const double *coor(_coords->begin());
7665 for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7667 double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7668 if(nodalI[1]-nodalI[0]>=3)
7670 for(int j=0;j<3;j++)
7672 int nodeId(nodal[nodalI[0]+1+j]);
7673 if(nodeId>=0 && nodeId<nbOfNodes)
7674 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7677 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7678 throw INTERP_KERNEL::Exception(oss.str().c_str());
7684 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7685 throw INTERP_KERNEL::Exception(oss.str().c_str());
7687 INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7688 retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7694 * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7697 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7700 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7701 da->checkAllocated();
7702 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7704 int nbOfTuples=da->getNumberOfTuples();
7705 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7706 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7707 c->alloc(2*nbOfTuples,1);
7708 cI->alloc(nbOfTuples+1,1);
7709 int *cp=c->getPointer();
7710 int *cip=cI->getPointer();
7712 for(int i=0;i<nbOfTuples;i++)
7714 *cp++=INTERP_KERNEL::NORM_POINT1;
7718 ret->setConnectivity(c,cI,true);
7722 * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7723 * Cells and nodes of
7724 * the first mesh precede cells and nodes of the second mesh within the result mesh.
7725 * \param [in] mesh1 - the first mesh.
7726 * \param [in] mesh2 - the second mesh.
7727 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7728 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7729 * is no more needed.
7730 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7731 * \throw If the coordinates array is not set in none of the meshes.
7732 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7733 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7735 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7737 std::vector<const MEDCouplingUMesh *> tmp(2);
7738 tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7739 return MergeUMeshes(tmp);
7743 * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7744 * Cells and nodes of
7745 * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7746 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7747 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7748 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7749 * is no more needed.
7750 * \throw If \a a.size() == 0.
7751 * \throw If \a a[ *i* ] == NULL.
7752 * \throw If the coordinates array is not set in none of the meshes.
7753 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7754 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7756 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7758 std::size_t sz=a.size();
7760 return MergeUMeshesLL(a);
7761 for(std::size_t ii=0;ii<sz;ii++)
7764 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7765 throw INTERP_KERNEL::Exception(oss.str().c_str());
7767 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7768 std::vector< const MEDCouplingUMesh * > aa(sz);
7770 for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7772 const MEDCouplingUMesh *cur=a[i];
7773 const DataArrayDouble *coo=cur->getCoords();
7775 spaceDim=coo->getNumberOfComponents();
7778 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7779 for(std::size_t i=0;i<sz;i++)
7781 bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7784 return MergeUMeshesLL(aa);
7789 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7792 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7793 std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7794 int meshDim=(*it)->getMeshDimension();
7795 int nbOfCells=(*it)->getNumberOfCells();
7796 int meshLgth=(*it++)->getMeshLength();
7797 for(;it!=a.end();it++)
7799 if(meshDim!=(*it)->getMeshDimension())
7800 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7801 nbOfCells+=(*it)->getNumberOfCells();
7802 meshLgth+=(*it)->getMeshLength();
7804 std::vector<const MEDCouplingPointSet *> aps(a.size());
7805 std::copy(a.begin(),a.end(),aps.begin());
7806 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7807 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7808 ret->setCoords(pts);
7809 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7810 c->alloc(meshLgth,1);
7811 int *cPtr=c->getPointer();
7812 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7813 cI->alloc(nbOfCells+1,1);
7814 int *cIPtr=cI->getPointer();
7818 for(it=a.begin();it!=a.end();it++)
7820 int curNbOfCell=(*it)->getNumberOfCells();
7821 const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7822 const int *curC=(*it)->_nodal_connec->getConstPointer();
7823 cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7824 for(int j=0;j<curNbOfCell;j++)
7826 const int *src=curC+curCI[j];
7828 for(;src!=curC+curCI[j+1];src++,cPtr++)
7836 offset+=curCI[curNbOfCell];
7837 offset2+=(*it)->getNumberOfNodes();
7840 ret->setConnectivity(c,cI,true);
7847 * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7848 * dimension and sharing the node coordinates array.
7849 * All cells of the first mesh precede all cells of the second mesh
7850 * within the result mesh.
7851 * \param [in] mesh1 - the first mesh.
7852 * \param [in] mesh2 - the second mesh.
7853 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7854 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7855 * is no more needed.
7856 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7857 * \throw If the meshes do not share the node coordinates array.
7858 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7859 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7861 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7863 std::vector<const MEDCouplingUMesh *> tmp(2);
7864 tmp[0]=mesh1; tmp[1]=mesh2;
7865 return MergeUMeshesOnSameCoords(tmp);
7869 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7870 * dimension and sharing the node coordinates array.
7871 * All cells of the *i*-th mesh precede all cells of the
7872 * (*i*+1)-th mesh within the result mesh.
7873 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7874 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7875 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7876 * is no more needed.
7877 * \throw If \a a.size() == 0.
7878 * \throw If \a a[ *i* ] == NULL.
7879 * \throw If the meshes do not share the node coordinates array.
7880 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7881 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7883 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7886 throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7887 for(std::size_t ii=0;ii<meshes.size();ii++)
7890 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7891 throw INTERP_KERNEL::Exception(oss.str().c_str());
7893 const DataArrayDouble *coords=meshes.front()->getCoords();
7894 int meshDim=meshes.front()->getMeshDimension();
7895 std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7897 int meshIndexLgth=0;
7898 for(;iter!=meshes.end();iter++)
7900 if(coords!=(*iter)->getCoords())
7901 throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7902 if(meshDim!=(*iter)->getMeshDimension())
7903 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7904 meshLgth+=(*iter)->getMeshLength();
7905 meshIndexLgth+=(*iter)->getNumberOfCells();
7907 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7908 nodal->alloc(meshLgth,1);
7909 int *nodalPtr=nodal->getPointer();
7910 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7911 nodalIndex->alloc(meshIndexLgth+1,1);
7912 int *nodalIndexPtr=nodalIndex->getPointer();
7914 for(iter=meshes.begin();iter!=meshes.end();iter++)
7916 const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7917 const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7918 int nbOfCells=(*iter)->getNumberOfCells();
7919 int meshLgth2=(*iter)->getMeshLength();
7920 nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7921 if(iter!=meshes.begin())
7922 nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7924 nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7927 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7928 ret->setName("merge");
7929 ret->setMeshDimension(meshDim);
7930 ret->setConnectivity(nodal,nodalIndex,true);
7931 ret->setCoords(coords);
7936 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7937 * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7938 * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7939 * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7940 * New" mode are returned for each input mesh.
7941 * \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7942 * \param [in] compType - specifies a cell comparison technique. For meaning of its
7943 * valid values [0,1,2], see zipConnectivityTraducer().
7944 * \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7945 * meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7946 * mesh. The caller is to delete each of the arrays using decrRef() as it is
7948 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7949 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7950 * is no more needed.
7951 * \throw If \a meshes.size() == 0.
7952 * \throw If \a meshes[ *i* ] == NULL.
7953 * \throw If the meshes do not share the node coordinates array.
7954 * \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7955 * \throw If the \a meshes are of different dimension (getMeshDimension()).
7956 * \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7957 * \throw If the nodal connectivity any of \a meshes includes an invalid id.
7959 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7961 //All checks are delegated to MergeUMeshesOnSameCoords
7962 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7963 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7964 corr.resize(meshes.size());
7965 std::size_t nbOfMeshes=meshes.size();
7967 const int *o2nPtr=o2n->getConstPointer();
7968 for(std::size_t i=0;i<nbOfMeshes;i++)
7970 DataArrayInt *tmp=DataArrayInt::New();
7971 int curNbOfCells=meshes[i]->getNumberOfCells();
7972 tmp->alloc(curNbOfCells,1);
7973 std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7974 offset+=curNbOfCells;
7975 tmp->setName(meshes[i]->getName());
7982 * Makes all given meshes share the nodal connectivity array. The common connectivity
7983 * array is created by concatenating the connectivity arrays of all given meshes. All
7984 * the given meshes must be of the same space dimension but dimension of cells **can
7985 * differ**. This method is particulary useful in MEDLoader context to build a \ref
7986 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7987 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7988 * \param [in,out] meshes - a vector of meshes to update.
7989 * \throw If any of \a meshes is NULL.
7990 * \throw If the coordinates array is not set in any of \a meshes.
7991 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7992 * \throw If \a meshes are of different space dimension.
7994 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
7996 std::size_t sz=meshes.size();
7999 std::vector< const DataArrayDouble * > coords(meshes.size());
8000 std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
8001 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
8005 (*it)->checkConnectivityFullyDefined();
8006 const DataArrayDouble *coo=(*it)->getCoords();
8011 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8012 oss << " has no coordinate array defined !";
8013 throw INTERP_KERNEL::Exception(oss.str().c_str());
8018 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8019 oss << " is null !";
8020 throw INTERP_KERNEL::Exception(oss.str().c_str());
8023 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
8024 std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
8025 int offset=(*it)->getNumberOfNodes();
8026 (*it++)->setCoords(res);
8027 for(;it!=meshes.end();it++)
8029 int oldNumberOfNodes=(*it)->getNumberOfNodes();
8030 (*it)->setCoords(res);
8031 (*it)->shiftNodeNumbersInConn(offset);
8032 offset+=oldNumberOfNodes;
8037 * Merges nodes coincident with a given precision within all given meshes that share
8038 * the nodal connectivity array. The given meshes **can be of different** mesh
8039 * dimension. This method is particulary useful in MEDLoader context to build a \ref
8040 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8041 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8042 * \param [in,out] meshes - a vector of meshes to update.
8043 * \param [in] eps - the precision used to detect coincident nodes (infinite norm).
8044 * \throw If any of \a meshes is NULL.
8045 * \throw If the \a meshes do not share the same node coordinates array.
8046 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8048 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
8052 std::set<const DataArrayDouble *> s;
8053 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8056 s.insert((*it)->getCoords());
8059 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 !";
8060 throw INTERP_KERNEL::Exception(oss.str().c_str());
8065 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 !";
8066 throw INTERP_KERNEL::Exception(oss.str().c_str());
8068 const DataArrayDouble *coo=*(s.begin());
8072 DataArrayInt *comm,*commI;
8073 coo->findCommonTuples(eps,-1,comm,commI);
8074 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
8075 int oldNbOfNodes=coo->getNumberOfTuples();
8077 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
8078 if(oldNbOfNodes==newNbOfNodes)
8080 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
8081 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8083 (*it)->renumberNodesInConn(o2n->getConstPointer());
8084 (*it)->setCoords(newCoords);
8089 * 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.
8090 * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
8091 * \param isQuad specifies the policy of connectivity.
8092 * @ret in/out parameter in which the result will be append
8094 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
8096 INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
8097 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
8098 ret.push_back(cm.getExtrudedType());
8099 int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
8102 case INTERP_KERNEL::NORM_POINT1:
8104 ret.push_back(connBg[1]);
8105 ret.push_back(connBg[1]+nbOfNodesPerLev);
8108 case INTERP_KERNEL::NORM_SEG2:
8110 int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
8111 ret.insert(ret.end(),conn,conn+4);
8114 case INTERP_KERNEL::NORM_SEG3:
8116 int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8117 ret.insert(ret.end(),conn,conn+8);
8120 case INTERP_KERNEL::NORM_QUAD4:
8122 int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8123 ret.insert(ret.end(),conn,conn+8);
8126 case INTERP_KERNEL::NORM_TRI3:
8128 int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8129 ret.insert(ret.end(),conn,conn+6);
8132 case INTERP_KERNEL::NORM_TRI6:
8134 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,
8135 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8136 ret.insert(ret.end(),conn,conn+15);
8139 case INTERP_KERNEL::NORM_QUAD8:
8142 connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8143 connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8144 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8146 ret.insert(ret.end(),conn,conn+20);
8149 case INTERP_KERNEL::NORM_POLYGON:
8151 std::back_insert_iterator< std::vector<int> > ii(ret);
8152 std::copy(connBg+1,connEnd,ii);
8154 std::reverse_iterator<const int *> rConnBg(connEnd);
8155 std::reverse_iterator<const int *> rConnEnd(connBg+1);
8156 std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8157 std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8158 for(std::size_t i=0;i<nbOfRadFaces;i++)
8161 int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8162 std::copy(conn,conn+4,ii);
8167 throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8172 * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8174 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8177 double v[3]={0.,0.,0.};
8178 std::size_t sz=std::distance(begin,end);
8183 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];
8184 v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8185 v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8187 double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8189 // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8190 // SEG3 forming a circle):
8191 if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8193 v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8194 for(std::size_t j=0;j<sz;j++)
8196 if (j%2) // current point i is quadratic, next point i+1 is standard
8199 ip1 = (j+1)%sz; // ip1 = "i+1"
8201 else // current point i is standard, next point i+1 is quadratic
8206 v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8207 v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8208 v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8210 ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8216 * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8218 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8220 std::vector<std::pair<int,int> > edges;
8221 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8222 const int *bgFace=begin;
8223 for(std::size_t i=0;i<nbOfFaces;i++)
8225 const int *endFace=std::find(bgFace+1,end,-1);
8226 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8227 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8229 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8230 if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8232 edges.push_back(p1);
8236 return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8240 * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8242 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8244 double vec0[3],vec1[3];
8245 std::size_t sz=std::distance(begin,end);
8247 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8248 int nbOfNodes=(int)sz/2;
8249 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8250 const double *pt0=coords+3*begin[0];
8251 const double *pt1=coords+3*begin[nbOfNodes];
8252 vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8253 return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8256 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8258 std::size_t sz=std::distance(begin,end);
8259 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8260 std::size_t nbOfNodes(sz/2);
8261 std::copy(begin,end,(int *)tmp);
8262 for(std::size_t j=1;j<nbOfNodes;j++)
8264 begin[j]=tmp[nbOfNodes-j];
8265 begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8269 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8271 std::size_t sz=std::distance(begin,end);
8273 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8274 double vec0[3],vec1[3];
8275 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8276 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];
8277 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;
8280 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8282 std::size_t sz=std::distance(begin,end);
8284 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8286 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8287 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8288 return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8292 * 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 )
8293 * 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
8296 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8297 * \param [in] coords the coordinates with nb of components exactly equal to 3
8298 * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8299 * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8300 * \param [out] res the result is put at the end of the vector without any alteration of the data.
8302 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8304 int nbFaces=std::count(begin+1,end,-1)+1;
8305 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8306 double *vPtr=v->getPointer();
8307 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8308 double *pPtr=p->getPointer();
8309 const int *stFaceConn=begin+1;
8310 for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8312 const int *endFaceConn=std::find(stFaceConn,end,-1);
8313 ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8314 stFaceConn=endFaceConn+1;
8316 pPtr=p->getPointer(); vPtr=v->getPointer();
8317 DataArrayInt *comm1=0,*commI1=0;
8318 v->findCommonTuples(eps,-1,comm1,commI1);
8319 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8320 const int *comm1Ptr=comm1->getConstPointer();
8321 const int *commI1Ptr=commI1->getConstPointer();
8322 int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8323 res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8325 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8326 mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8327 mm->finishInsertingCells();
8329 for(int i=0;i<nbOfGrps1;i++)
8331 int vecId=comm1Ptr[commI1Ptr[i]];
8332 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8333 DataArrayInt *comm2=0,*commI2=0;
8334 tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8335 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8336 const int *comm2Ptr=comm2->getConstPointer();
8337 const int *commI2Ptr=commI2->getConstPointer();
8338 int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8339 for(int j=0;j<nbOfGrps2;j++)
8341 if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8343 res->insertAtTheEnd(begin,end);
8344 res->pushBackSilent(-1);
8348 int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8349 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8350 ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8351 DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8352 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8353 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8354 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8355 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8356 const int *idsNodePtr=idsNode->getConstPointer();
8357 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];
8358 double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8359 double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8360 if(std::abs(norm)>eps)
8362 double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8363 mm3->rotate(center,vec,angle);
8365 mm3->changeSpaceDimension(2);
8366 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8367 const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8368 const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8369 int nbOfCells=mm4->getNumberOfCells();
8370 for(int k=0;k<nbOfCells;k++)
8373 for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8374 res->pushBackSilent(idsNodePtr[*work]);
8375 res->pushBackSilent(-1);
8380 res->popBackSilent();
8384 * 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
8385 * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8387 * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8388 * \param [in] coords coordinates expected to have 3 components.
8389 * \param [in] begin start of the nodal connectivity of the face.
8390 * \param [in] end end of the nodal connectivity (excluded) of the face.
8391 * \param [out] v the normalized vector of size 3
8392 * \param [out] p the pos of plane
8394 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8396 std::size_t nbPoints=std::distance(begin,end);
8398 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8399 double vec[3]={0.,0.,0.};
8401 bool refFound=false;
8402 for(;j<nbPoints-1 && !refFound;j++)
8404 vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8405 vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8406 vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8407 double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8411 vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8414 for(std::size_t i=j;i<nbPoints-1;i++)
8417 curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8418 curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8419 curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8420 double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8423 curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8424 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];
8425 norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8428 v[0]/=norm; v[1]/=norm; v[2]/=norm;
8429 *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8433 throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8437 * This method tries to obtain a well oriented polyhedron.
8438 * If the algorithm fails, an exception will be thrown.
8440 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8442 std::list< std::pair<int,int> > edgesOK,edgesFinished;
8443 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8444 std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8446 int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8447 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8448 for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8450 while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8453 std::size_t smthChanged=0;
8454 for(std::size_t i=0;i<nbOfFaces;i++)
8456 endFace=std::find(bgFace+1,end,-1);
8457 nbOfEdgesInFace=std::distance(bgFace,endFace);
8461 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8463 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8464 std::pair<int,int> p2(p1.second,p1.first);
8465 bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8466 bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8467 if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8472 std::reverse(bgFace+1,endFace);
8473 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8475 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8476 std::pair<int,int> p2(p1.second,p1.first);
8477 if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8478 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8479 if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8480 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8481 std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8482 if(it!=edgesOK.end())
8485 edgesFinished.push_back(p1);
8488 edgesOK.push_back(p1);
8495 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8497 if(!edgesOK.empty())
8498 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8499 if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8500 {//not lucky ! The first face was not correctly oriented : reorient all faces...
8502 for(std::size_t i=0;i<nbOfFaces;i++)
8504 endFace=std::find(bgFace+1,end,-1);
8505 std::reverse(bgFace+1,endFace);
8511 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8513 int nbOfNodesExpected(skin->getNumberOfNodes());
8514 const int *n2oPtr(n2o->getConstPointer());
8515 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8516 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8517 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8518 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8519 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8520 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8521 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_POLYGON;
8522 if(nbOfNodesExpected<1)
8524 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8525 *work++=n2oPtr[prevNode];
8526 for(int i=1;i<nbOfNodesExpected;i++)
8528 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8530 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8531 conn.erase(prevNode);
8534 int curNode(*(conn.begin()));
8535 *work++=n2oPtr[curNode];
8536 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8537 shar.erase(prevCell);
8540 prevCell=*(shar.begin());
8544 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8547 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8550 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8555 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8557 int nbOfNodesExpected(skin->getNumberOfNodes());
8558 int nbOfTurn(nbOfNodesExpected/2);
8559 const int *n2oPtr(n2o->getConstPointer());
8560 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8561 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8562 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8563 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8564 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8565 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8566 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_QPOLYG;
8567 if(nbOfNodesExpected<1)
8569 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8570 *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8571 for(int i=1;i<nbOfTurn;i++)
8573 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8575 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8576 conn.erase(prevNode);
8579 int curNode(*(conn.begin()));
8580 *work=n2oPtr[curNode];
8581 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8582 shar.erase(prevCell);
8585 int curCell(*(shar.begin()));
8586 work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8592 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8595 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8598 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8604 * This method makes the assumption spacedimension == meshdimension == 2.
8605 * This method works only for linear cells.
8607 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8609 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8611 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8612 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8613 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8614 int oldNbOfNodes(skin->getNumberOfNodes());
8615 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8616 int nbOfNodesExpected(skin->getNumberOfNodes());
8617 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8618 int nbCells(skin->getNumberOfCells());
8619 if(nbCells==nbOfNodesExpected)
8620 return buildUnionOf2DMeshLinear(skin,n2o);
8621 else if(2*nbCells==nbOfNodesExpected)
8622 return buildUnionOf2DMeshQuadratic(skin,n2o);
8624 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8628 * This method makes the assumption spacedimension == meshdimension == 3.
8629 * This method works only for linear cells.
8631 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8633 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8635 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8636 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8637 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8638 const int *conn=m->getNodalConnectivity()->getConstPointer();
8639 const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8640 int nbOfCells=m->getNumberOfCells();
8641 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8642 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED;
8645 work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8646 for(int i=1;i<nbOfCells;i++)
8649 work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8655 * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8656 * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8658 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8662 for(int i=0;i<nbOfNodesInCell;i++)
8663 w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8664 else if(spaceDim==2)
8666 for(int i=0;i<nbOfNodesInCell;i++)
8668 w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8673 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8676 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8678 int nbOfCells=getNumberOfCells();
8680 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8681 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};
8682 ofs << " <" << getVTKDataSetType() << ">\n";
8683 ofs << " <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8684 ofs << " <PointData>\n" << pointData << std::endl;
8685 ofs << " </PointData>\n";
8686 ofs << " <CellData>\n" << cellData << std::endl;
8687 ofs << " </CellData>\n";
8688 ofs << " <Points>\n";
8689 if(getSpaceDimension()==3)
8690 _coords->writeVTK(ofs,8,"Points",byteData);
8693 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8694 coo->writeVTK(ofs,8,"Points",byteData);
8696 ofs << " </Points>\n";
8697 ofs << " <Cells>\n";
8698 const int *cPtr=_nodal_connec->getConstPointer();
8699 const int *cIPtr=_nodal_connec_index->getConstPointer();
8700 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8701 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8702 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8703 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8704 int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8705 int szFaceOffsets=0,szConn=0;
8706 for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8709 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8712 *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8713 w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8717 int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8718 *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8719 std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8720 *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8721 w4=std::copy(c.begin(),c.end(),w4);
8724 types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8725 types->writeVTK(ofs,8,"UInt8","types",byteData);
8726 offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8727 if(szFaceOffsets!=0)
8728 {//presence of Polyhedra
8729 connectivity->reAlloc(szConn);
8730 faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8731 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8732 w1=faces->getPointer();
8733 for(int i=0;i<nbOfCells;i++)
8734 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8736 int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8738 const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8739 for(int j=0;j<nbFaces;j++)
8741 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8742 *w1++=(int)std::distance(w6,w5);
8743 w1=std::copy(w6,w5,w1);
8747 faces->writeVTK(ofs,8,"Int32","faces",byteData);
8749 connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8750 ofs << " </Cells>\n";
8751 ofs << " </Piece>\n";
8752 ofs << " </" << getVTKDataSetType() << ">\n";
8755 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8757 stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8759 { stream << " Not set !"; return ; }
8760 stream << " Mesh dimension : " << _mesh_dim << ".";
8764 { stream << " No coordinates set !"; return ; }
8765 if(!_coords->isAllocated())
8766 { stream << " Coordinates set but not allocated !"; return ; }
8767 stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8768 stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8769 if(!_nodal_connec_index)
8770 { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8771 if(!_nodal_connec_index->isAllocated())
8772 { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8773 int lgth=_nodal_connec_index->getNumberOfTuples();
8774 int cpt=_nodal_connec_index->getNumberOfComponents();
8775 if(cpt!=1 || lgth<1)
8777 stream << std::endl << "Number of cells : " << lgth-1 << ".";
8780 std::string MEDCouplingUMesh::getVTKDataSetType() const
8782 return std::string("UnstructuredGrid");
8785 std::string MEDCouplingUMesh::getVTKFileExtension() const
8787 return std::string("vtu");
8791 * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8792 * returns a result mesh constituted by polygons.
8793 * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8794 * all nodes from m2.
8795 * The meshes should be in 2D space. In
8796 * addition, returns two arrays mapping cells of the result mesh to cells of the input
8798 * \param [in] m1 - the first input mesh which is a partitioned object. The mesh must be so that each point in the space covered by \a m1
8799 * must be covered exactly by one entity, \b no \b more. If it is not the case, some tools are available to heal the mesh (conformize2D, mergeNodes)
8800 * \param [in] m2 - the second input mesh which is a partition tool. The mesh must be so that each point in the space covered by \a m2
8801 * must be covered exactly by one entity, \b no \b more. If it is not the case, some tools are available to heal the mesh (conformize2D, mergeNodes)
8802 * \param [in] eps - precision used to detect coincident mesh entities.
8803 * \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8804 * cell an id of the cell of \a m1 it comes from. The caller is to delete
8805 * this array using decrRef() as it is no more needed.
8806 * \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8807 * cell an id of the cell of \a m2 it comes from. -1 value means that a
8808 * result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8809 * any cell of \a m2. The caller is to delete this array using decrRef() as
8810 * it is no more needed.
8811 * \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8812 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8813 * is no more needed.
8814 * \throw If the coordinates array is not set in any of the meshes.
8815 * \throw If the nodal connectivity of cells is not defined in any of the meshes.
8816 * \throw If any of the meshes is not a 2D mesh in 2D space.
8818 * \sa conformize2D, mergeNodes
8820 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8821 double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8824 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
8825 m1->checkFullyDefined();
8826 m2->checkFullyDefined();
8827 if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8828 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!");
8830 // Step 1: compute all edge intersections (new nodes)
8831 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8832 MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
8833 DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8834 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
8835 IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
8836 m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8837 addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
8838 revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8839 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8840 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8842 // Step 2: re-order newly created nodes according to the ordering found in m2
8843 std::vector< std::vector<int> > intersectEdge2;
8844 BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8845 subDiv2.clear(); dd5=0; dd6=0;
8848 std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8849 std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8850 BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8851 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8853 // Step 4: Prepare final result:
8854 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
8855 addCooDa->alloc((int)(addCoo.size())/2,2);
8856 std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8857 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
8858 addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8859 std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8860 std::vector<const DataArrayDouble *> coordss(4);
8861 coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8862 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
8863 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
8864 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8865 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8866 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8867 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8868 ret->setConnectivity(conn,connI,true);
8869 ret->setCoords(coo);
8870 cellNb1=c1.retn(); cellNb2=c2.retn();
8876 bool IsColinearOfACellOf(const std::vector< std::vector<int> >& intersectEdge1, const std::vector<int>& candidates, int start, int stop, int& retVal)
8878 if(candidates.empty())
8880 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
8882 const std::vector<int>& pool(intersectEdge1[*it]);
8883 int tmp[2]; tmp[0]=start; tmp[1]=stop;
8884 if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
8889 tmp[0]=stop; tmp[1]=start;
8890 if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
8899 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,
8900 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInRetColinear, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInMesh1DForIdsInRetColinear)
8902 idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1);
8903 idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1);
8904 int nCells(mesh1D->getNumberOfCells());
8905 if(nCells!=(int)intersectEdge2.size())
8906 throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
8907 const DataArrayDouble *coo2(mesh1D->getCoords());
8908 const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
8909 const double *coo2Ptr(coo2->begin());
8910 int offset1(coords1->getNumberOfTuples());
8911 int offset2(offset1+coo2->getNumberOfTuples());
8912 int offset3(offset2+addCoo.size()/2);
8913 std::vector<double> addCooQuad;
8914 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
8915 int tmp[4],cicnt(0),kk(0);
8916 for(int i=0;i<nCells;i++)
8918 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
8919 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
8920 const std::vector<int>& subEdges(intersectEdge2[i]);
8921 int nbSubEdge(subEdges.size()/2);
8922 for(int j=0;j<nbSubEdge;j++,kk++)
8924 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));
8925 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
8926 INTERP_KERNEL::Edge *e2Ptr(e2);
8927 std::map<int,int>::const_iterator itm;
8928 if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
8930 tmp[0]=INTERP_KERNEL::NORM_SEG3;
8931 itm=mergedNodes.find(subEdges[2*j]);
8932 tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
8933 itm=mergedNodes.find(subEdges[2*j+1]);
8934 tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
8935 tmp[3]=offset3+(int)addCooQuad.size()/2;
8937 e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2);
8939 cOut->insertAtTheEnd(tmp,tmp+4);
8940 ciOut->pushBackSilent(cicnt);
8944 tmp[0]=INTERP_KERNEL::NORM_SEG2;
8945 itm=mergedNodes.find(subEdges[2*j]);
8946 tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
8947 itm=mergedNodes.find(subEdges[2*j+1]);
8948 tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
8950 cOut->insertAtTheEnd(tmp,tmp+3);
8951 ciOut->pushBackSilent(cicnt);
8954 if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00))
8956 idsInRetColinear->pushBackSilent(kk);
8957 idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00);
8962 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
8963 ret->setConnectivity(cOut,ciOut,true);
8964 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr3(DataArrayDouble::New());
8965 arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
8966 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
8967 std::vector<const DataArrayDouble *> coordss(4);
8968 coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
8969 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
8970 ret->setCoords(arr);
8974 MEDCouplingUMesh *BuildRefined2DCellLinear(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
8976 std::vector<int> allEdges;
8977 for(const int *it2(descBg);it2!=descEnd;it2++)
8979 const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
8981 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
8983 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
8985 std::size_t nb(allEdges.size());
8987 throw INTERP_KERNEL::Exception("BuildRefined2DCellLinear : internal error 1 !");
8988 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
8989 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
8990 ret->setCoords(coords);
8991 ret->allocateCells(1);
8992 std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
8993 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
8994 connOut[kk]=allEdges[2*kk];
8995 ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]);
8999 MEDCouplingUMesh *BuildRefined2DCellQuadratic(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9001 const int *c(mesh2D->getNodalConnectivity()->begin()),*ci(mesh2D->getNodalConnectivityIndex()->begin());
9002 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[cellIdInMesh2D]]));
9004 unsigned sz(cm.getNumberOfSons2(c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1));
9005 if(sz!=std::distance(descBg,descEnd))
9006 throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 1 !");
9007 INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]]);
9008 std::vector<int> allEdges,centers;
9009 const double *coordsPtr(coords->begin());
9010 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
9011 int offset(coords->getNumberOfTuples());
9012 for(const int *it2(descBg);it2!=descEnd;it2++,ii++)
9014 INTERP_KERNEL::NormalizedCellType typeOfSon;
9015 cm.fillSonCellNodalConnectivity2(ii,c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1,tmpPtr,typeOfSon);
9016 const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9018 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9020 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9022 centers.push_back(tmpPtr[2]);//special case where no subsplit of edge -> reuse the original center.
9024 {//the current edge has been subsplit -> create corresponding centers.
9025 std::size_t nbOfCentersToAppend(edge1.size()/2);
9026 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9027 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpPtr,coordsPtr,m));
9028 std::vector<int>::const_iterator it3(allEdges.end()-edge1.size());
9029 for(std::size_t k=0;k<nbOfCentersToAppend;k++)
9032 const double *aa(coordsPtr+2*(*it3++));
9033 const double *bb(coordsPtr+2*(*it3++));
9034 ee->getMiddleOfPoints(aa,bb,tmpp);
9035 addCoo->insertAtTheEnd(tmpp,tmpp+2);
9036 centers.push_back(offset+k);
9040 std::size_t nb(allEdges.size());
9042 throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 2 !");
9043 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9044 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9046 ret->setCoords(coords);
9049 addCoo->rearrange(2);
9050 addCoo=DataArrayDouble::Aggregate(coords,addCoo);
9051 ret->setCoords(addCoo);
9053 ret->allocateCells(1);
9054 std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9055 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9056 connOut[kk]=allEdges[2*kk];
9057 connOut.insert(connOut.end(),centers.begin(),centers.end());
9058 ret->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,connOut.size(),&connOut[0]);
9063 * This method creates a refinement of a cell in \a mesh2D. Those cell is defined by descending connectivity and the sorted subdivided nodal connectivity
9066 * \param [in] mesh2D - The origin 2D mesh. \b Warning \b coords are not those of \a mesh2D. But mesh2D->getCoords()==coords[:mesh2D->getNumberOfNodes()]
9068 MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9070 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(mesh2D->getTypeOfCell(cellIdInMesh2D)));
9071 if(!cm.isQuadratic())
9072 return BuildRefined2DCellLinear(coords,descBg,descEnd,intersectEdge1);
9074 return BuildRefined2DCellQuadratic(coords,mesh2D,cellIdInMesh2D,descBg,descEnd,intersectEdge1);
9077 void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector<int>& conn, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edges)
9080 for(std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >::const_iterator it=edges.begin();it!=edges.end();it++)
9082 const INTERP_KERNEL::Edge *ee(*it);
9083 if(dynamic_cast<const INTERP_KERNEL::EdgeArcCircle *>(ee))
9087 mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]);
9090 const double *coo(mesh2D->getCoords()->begin());
9091 std::size_t sz(conn.size());
9092 std::vector<double> addCoo;
9093 std::vector<int> conn2(conn);
9094 int offset(mesh2D->getNumberOfNodes());
9095 for(std::size_t i=0;i<sz;i++)
9098 edges[(i+1)%sz]->getMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);// tony a chier i+1 -> i
9099 addCoo.insert(addCoo.end(),tmp,tmp+2);
9100 conn2.push_back(offset+(int)i);
9102 mesh2D->getCoords()->rearrange(1);
9103 mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size());
9104 mesh2D->getCoords()->rearrange(2);
9105 mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]);
9110 * \b WARNING edges in out1 coming from \a splitMesh1D are \b NOT oriented because only used for equation of curve.
9112 * This method cuts in 2 parts the input 2D cell given using boundaries description (\a edge1Bis and \a edge1BisPtr) using
9113 * a set of edges defined in \a splitMesh1D.
9115 void BuildMesh2DCutInternal2(const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& edge1Bis, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edge1BisPtr,
9116 std::vector< std::vector<int> >& out0, std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& out1)
9118 std::size_t nb(edge1Bis.size()/2);
9119 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9120 int iEnd(splitMesh1D->getNumberOfCells());
9122 throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal2 : internal error ! input 1D mesh must have at least one cell !");
9124 const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9125 for(ii=0;ii<nb && edge1Bis[2*ii]!=cSplitPtr[ciSplitPtr[0]+1];ii++);
9126 for(jj=ii;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd-1]+2];jj++);
9129 {//the edges splitMesh1D[iStart:iEnd] does not fully cut the current 2D cell -> single output cell
9130 out0.resize(1); out1.resize(1);
9131 std::vector<int>& connOut(out0[0]);
9132 connOut.resize(nbOfEdgesOf2DCellSplit);
9133 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr(out1[0]);
9134 edgesPtr.resize(nbOfEdgesOf2DCellSplit);
9135 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9137 connOut[kk]=edge1Bis[2*kk];
9138 edgesPtr[kk]=edge1BisPtr[2*kk];
9143 // [i,iEnd[ contains the
9144 out0.resize(2); out1.resize(2);
9145 std::vector<int>& connOutLeft(out0[0]);
9146 std::vector<int>& connOutRight(out0[1]);//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1]
9147 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eleft(out1[0]);
9148 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eright(out1[1]);
9149 for(std::size_t k=ii;k<jj+1;k++)
9150 { connOutLeft.push_back(edge1Bis[2*k+1]); eleft.push_back(edge1BisPtr[2*k+1]); }
9151 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > ees(iEnd);
9152 for(int ik=0;ik<iEnd;ik++)
9154 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9155 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9158 for(int ik=iEnd-1;ik>=0;ik--)
9159 connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]);
9160 for(std::size_t k=jj+1;k<nbOfEdgesOf2DCellSplit+ii;k++)
9161 { connOutRight.push_back(edge1Bis[2*k+1]); eright.push_back(edge1BisPtr[2*k+1]); }
9162 eleft.insert(eleft.end(),ees.rbegin(),ees.rend());
9163 for(int ik=0;ik<iEnd;ik++)
9164 connOutRight.push_back(cSplitPtr[ciSplitPtr[ik]+2]);
9165 eright.insert(eright.end(),ees.begin(),ees.end());
9177 CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9179 std::vector<int> _edges;
9180 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > _edges_ptr;
9183 CellInfo::CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr)
9185 std::size_t nbe(edges.size());
9186 std::vector<int> edges2(2*nbe); std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edgesPtr2(2*nbe);
9187 for(std::size_t i=0;i<nbe;i++)
9189 edges2[2*i]=edges[i]; edges2[2*i+1]=edges[(i+1)%nbe];
9190 edgesPtr2[2*i]=edgesPtr[(i+1)%nbe]; edgesPtr2[2*i+1]=edgesPtr[(i+1)%nbe];//tony a chier
9192 _edges.resize(4*nbe); _edges_ptr.resize(4*nbe);
9193 std::copy(edges2.begin(),edges2.end(),_edges.begin()); std::copy(edges2.begin(),edges2.end(),_edges.begin()+2*nbe);
9194 std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()); std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()+2*nbe);
9200 EdgeInfo(int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh):_istart(istart),_iend(iend),_mesh(mesh),_left(-7),_right(-7) { }
9201 EdgeInfo(int istart, int iend, int pos, const MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge>& edge):_istart(istart),_iend(iend),_edge(edge),_left(pos),_right(pos+1) { }
9202 bool isInMyRange(int pos) const { return pos>=_istart && pos<_iend; }
9203 void somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9204 void feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const;
9208 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _mesh;
9209 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> _edge;
9214 void EdgeInfo::somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9216 const MEDCouplingUMesh *mesh(_mesh);
9222 { _left++; _right++; return ; }
9225 bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9226 if((isLeft && isRight) || (!isLeft && !isRight))
9227 throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 1 !");
9238 bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9239 if((isLeft && isRight) || (!isLeft && !isRight))
9240 throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 2 !");
9255 void EdgeInfo::feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const
9257 const MEDCouplingUMesh *mesh(_mesh);
9260 neighbors[0]=offset+_left; neighbors[1]=offset+_right;
9263 {// not fully splitting cell case
9264 if(mesh2D->getNumberOfCells()==1)
9265 {//little optimization. 1 cell no need to find in which cell mesh is !
9266 neighbors[0]=offset; neighbors[1]=offset;
9271 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9272 int cellId(mesh2D->getCellContainingPoint(barys->begin(),eps));
9274 throw INTERP_KERNEL::Exception("EdgeInfo::feedEdgeInfoAt : internal error !");
9275 neighbors[0]=offset+cellId; neighbors[1]=offset+cellId;
9280 class VectorOfCellInfo
9283 VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9284 std::size_t size() const { return _pool.size(); }
9285 int getPositionOf(double eps, const MEDCouplingUMesh *mesh) const;
9286 void setMeshAt(int pos, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh, int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh1DInCase, const std::vector< std::vector<int> >& edges, const std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& edgePtrs);
9287 const std::vector<int>& getConnOf(int pos) const { return get(pos)._edges; }
9288 const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& getEdgePtrOf(int pos) const { return get(pos)._edges_ptr; }
9289 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> getZeMesh() const { return _ze_mesh; }
9290 void feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const;
9292 int getZePosOfEdgeGivenItsGlobalId(int pos) const;
9293 void updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9294 const CellInfo& get(int pos) const;
9295 CellInfo& get(int pos);
9297 std::vector<CellInfo> _pool;
9298 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _ze_mesh;
9299 std::vector<EdgeInfo> _edge_info;
9302 VectorOfCellInfo::VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr):_pool(1)
9304 _pool[0]._edges=edges;
9305 _pool[0]._edges_ptr=edgesPtr;
9308 int VectorOfCellInfo::getPositionOf(double eps, const MEDCouplingUMesh *mesh) const
9311 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : empty !");
9314 const MEDCouplingUMesh *zeMesh(_ze_mesh);
9316 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : null aggregated mesh !");
9317 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9318 return zeMesh->getCellContainingPoint(barys->begin(),eps);
9321 void VectorOfCellInfo::setMeshAt(int pos, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh, int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh1DInCase, const std::vector< std::vector<int> >& edges, const std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& edgePtrs)
9323 get(pos);//to check pos
9324 bool isFast(pos==0 && _pool.size()==1);
9325 std::size_t sz(edges.size());
9326 // dealing with edges
9328 _edge_info.push_back(EdgeInfo(istart,iend,mesh1DInCase));
9330 _edge_info.push_back(EdgeInfo(istart,iend,pos,edgePtrs[0].back()));
9332 std::vector<CellInfo> pool(_pool.size()-1+sz);
9333 for(int i=0;i<pos;i++)
9335 for(std::size_t j=0;j<sz;j++)
9336 pool[pos+j]=CellInfo(edges[j],edgePtrs[j]);
9337 for(int i=pos+1;i<(int)_pool.size();i++)
9338 pool[i+sz-1]=_pool[i];
9342 updateEdgeInfo(pos,edgePtrs[0],edgePtrs[1]);
9350 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > ms;
9353 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(0,pos,true)));
9357 if(pos<_ze_mesh->getNumberOfCells()-1)
9359 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(pos+1,_ze_mesh->getNumberOfCells(),true)));
9362 std::vector< const MEDCouplingUMesh *> ms2(ms.size());
9363 for(std::size_t j=0;j<ms2.size();j++)
9365 _ze_mesh=MEDCouplingUMesh::MergeUMeshesOnSameCoords(ms2);
9368 void VectorOfCellInfo::feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const
9370 _edge_info[getZePosOfEdgeGivenItsGlobalId(pos)].feedEdgeInfoAt(eps,_ze_mesh,offset,neighbors);
9373 int VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId(int pos) const
9376 throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id ! Must be >=0 !");
9378 for(std::vector<EdgeInfo>::const_iterator it=_edge_info.begin();it!=_edge_info.end();it++,ret++)
9380 if((*it).isInMyRange(pos))
9383 throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id !");
9386 void VectorOfCellInfo::updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9388 get(pos);//to check;
9389 if(_edge_info.empty())
9391 std::size_t sz(_edge_info.size()-1);
9392 for(std::size_t i=0;i<sz;i++)
9393 _edge_info[i].somethingHappendAt(pos,newLeft,newRight);
9396 const CellInfo& VectorOfCellInfo::get(int pos) const
9398 if(pos<0 || pos>=(int)_pool.size())
9399 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get const : invalid pos !");
9403 CellInfo& VectorOfCellInfo::get(int pos)
9405 if(pos<0 || pos>=(int)_pool.size())
9406 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get : invalid pos !");
9412 * - a \b closed set of edges ( \a allEdges and \a allEdgesPtr ) that defines the split descending 2D cell.
9413 * - \a splitMesh1D a split 2D curve mesh contained into 2D cell defined above.
9415 * This method returns the 2D mesh and feeds \a idsLeftRight using offset.
9417 * Algorithm : \a splitMesh1D is cut into contiguous parts. Each contiguous parts will build incrementally the output 2D cells.
9419 * \param [in] allEdges a list of pairs (beginNode, endNode). Linked with \a allEdgesPtr to get the equation of edge.
9421 MEDCouplingUMesh *BuildMesh2DCutInternal(double eps, const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& allEdges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& allEdgesPtr, int offset,
9422 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9424 int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells());
9425 if(nbCellsInSplitMesh1D==0)
9426 throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal : internal error ! input 1D mesh must have at least one cell !");
9427 const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9428 std::size_t nb(allEdges.size()),jj;
9430 throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !");
9431 std::vector<int> edge1Bis(nb*2);
9432 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edge1BisPtr(nb*2);
9433 std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin());
9434 std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb);
9435 std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin());
9436 std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb);
9438 idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(nbCellsInSplitMesh1D*2); idsLeftRight->fillWithValue(-2); idsLeftRight->rearrange(2);
9439 int *idsLeftRightPtr(idsLeftRight->getPointer());
9440 VectorOfCellInfo pool(edge1Bis,edge1BisPtr);
9441 for(int iStart=0;iStart<nbCellsInSplitMesh1D;)
9442 {// split [0:nbCellsInSplitMesh1D) in contiguous parts [iStart:iEnd)
9444 for(;iEnd<nbCellsInSplitMesh1D;)
9446 for(jj=0;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd]+2];jj++);
9452 if(iEnd<nbCellsInSplitMesh1D)
9455 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfSplitMesh1D(static_cast<MEDCouplingUMesh *>(splitMesh1D->buildPartOfMySelf2(iStart,iEnd,1,true)));
9456 int pos(pool.getPositionOf(eps,partOfSplitMesh1D));
9458 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>retTmp(MEDCouplingUMesh::New("",2));
9459 retTmp->setCoords(splitMesh1D->getCoords());
9460 retTmp->allocateCells();
9462 std::vector< std::vector<int> > out0;
9463 std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > > out1;
9465 BuildMesh2DCutInternal2(partOfSplitMesh1D,pool.getConnOf(pos),pool.getEdgePtrOf(pos),out0,out1);
9466 for(std::size_t cnt=0;cnt<out0.size();cnt++)
9467 AddCellInMesh2D(retTmp,out0[cnt],out1[cnt]);
9468 pool.setMeshAt(pos,retTmp,iStart,iEnd,partOfSplitMesh1D,out0,out1);
9472 for(int mm=0;mm<nbCellsInSplitMesh1D;mm++)
9473 pool.feedEdgeInfoAt(eps,mm,offset,idsLeftRightPtr+2*mm);
9474 return pool.getZeMesh().retn();
9477 MEDCouplingUMesh *BuildMesh2DCutFrom(double eps, int cellIdInMesh2D, const MEDCouplingUMesh *mesh2DDesc, const MEDCouplingUMesh *splitMesh1D,
9478 const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1, int offset,
9479 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9481 const int *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin());
9483 std::vector<int> allEdges;
9484 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > allEdgesPtr; // for each sub edge in splitMesh2D the uncut Edge object of the original mesh2D
9485 for(const int *it(descBg);it!=descEnd;it++) // for all edges in the descending connectivity of the 2D mesh in relative Fortran mode
9487 int edgeId(std::abs(*it)-1);
9488 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9489 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m));
9490 const std::vector<int>& edge1(intersectEdge1[edgeId]);
9492 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9494 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9495 std::size_t sz(edge1.size());
9496 for(std::size_t cnt=0;cnt<sz;cnt++)
9497 allEdgesPtr.push_back(ee);
9500 return BuildMesh2DCutInternal(eps,splitMesh1D,allEdges,allEdgesPtr,offset,idsLeftRight);
9503 bool AreEdgeEqual(const double *coo2D, const INTERP_KERNEL::CellModel& typ1, const int *conn1, const INTERP_KERNEL::CellModel& typ2, const int *conn2, double eps)
9505 if(!typ1.isQuadratic() && !typ2.isQuadratic())
9506 {//easy case comparison not
9507 return conn1[0]==conn2[0] && conn1[1]==conn2[1];
9509 else if(typ1.isQuadratic() && typ2.isQuadratic())
9511 bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9514 if(conn1[2]==conn2[2])
9516 const double *a(coo2D+2*conn1[2]),*b(coo2D+2*conn2[2]);
9517 double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9521 {//only one is quadratic
9522 bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9525 const double *a(0),*bb(0),*be(0);
9526 if(typ1.isQuadratic())
9528 a=coo2D+2*conn1[2]; bb=coo2D+2*conn2[0]; be=coo2D+2*conn2[1];
9532 a=coo2D+2*conn2[2]; bb=coo2D+2*conn1[0]; be=coo2D+2*conn1[1];
9534 double b[2]; b[0]=(be[0]+bb[0])/2.; b[1]=(be[1]+bb[1])/2.;
9535 double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9541 * This method returns among the cellIds [ \a candidatesIn2DBg , \a candidatesIn2DEnd ) in \a mesh2DSplit those exactly sharing \a cellIdInMesh1DSplitRelative in \a mesh1DSplit.
9542 * \a mesh2DSplit and \a mesh1DSplit are expected to share the coordinates array.
9544 * \param [in] cellIdInMesh1DSplitRelative is in Fortran mode using sign to specify direction.
9546 int FindRightCandidateAmong(const MEDCouplingUMesh *mesh2DSplit, const int *candidatesIn2DBg, const int *candidatesIn2DEnd, const MEDCouplingUMesh *mesh1DSplit, int cellIdInMesh1DSplitRelative, double eps)
9548 if(candidatesIn2DEnd==candidatesIn2DBg)
9549 throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 1 !");
9550 const double *coo(mesh2DSplit->getCoords()->begin());
9551 if(std::distance(candidatesIn2DBg,candidatesIn2DEnd)==1)
9552 return *candidatesIn2DBg;
9553 int edgeId(std::abs(cellIdInMesh1DSplitRelative)-1);
9554 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur1D(static_cast<MEDCouplingUMesh *>(mesh1DSplit->buildPartOfMySelf(&edgeId,&edgeId+1,true)));
9555 if(cellIdInMesh1DSplitRelative<0)
9556 cur1D->changeOrientationOfCells();
9557 const int *c1D(cur1D->getNodalConnectivity()->begin());
9558 const INTERP_KERNEL::CellModel& ref1DType(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c1D[0]));
9559 for(const int *it=candidatesIn2DBg;it!=candidatesIn2DEnd;it++)
9561 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur2D(static_cast<MEDCouplingUMesh *>(mesh2DSplit->buildPartOfMySelf(it,it+1,true)));
9562 const int *c(cur2D->getNodalConnectivity()->begin()),*ci(cur2D->getNodalConnectivityIndex()->begin());
9563 const INTERP_KERNEL::CellModel &cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[0]]));
9564 unsigned sz(cm.getNumberOfSons2(c+ci[0]+1,ci[1]-ci[0]-1));
9565 INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[1]-ci[0]]);
9566 for(unsigned it2=0;it2<sz;it2++)
9568 INTERP_KERNEL::NormalizedCellType typeOfSon;
9569 cm.fillSonCellNodalConnectivity2(it2,c+ci[0]+1,ci[1]-ci[0]-1,tmpPtr,typeOfSon);
9570 const INTERP_KERNEL::CellModel &curCM(INTERP_KERNEL::CellModel::GetCellModel(typeOfSon));
9571 if(AreEdgeEqual(coo,ref1DType,c1D+1,curCM,tmpPtr,eps))
9575 throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 2 ! Unable to find the edge among split cell !");
9581 * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
9582 * Thus the final result contains the aggregation of nodes of \a mesh2D, then nodes of \a mesh1D, then new nodes that are the result of the intersection
9583 * and finaly, in case of quadratic polygon the centers of edges new nodes.
9584 * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
9586 * \param [in] mesh2D - the 2D mesh (spacedim=meshdim=2) to be intersected using \a mesh1D tool. The mesh must be so that each point in the space covered by \a mesh2D
9587 * must be covered exactly by one entity, \b no \b more. If it is not the case, some tools are available to heal the mesh (conformize2D, mergeNodes)
9588 * \param [in] mesh1D - the 1D mesh (spacedim=2 meshdim=1) the is the tool that will be used to intersect \a mesh2D. \a mesh1D must be ordered consecutively. If it is not the case
9589 * you can invoke orderConsecutiveCells1D on \a mesh1D.
9590 * \param [in] eps - precision used to perform intersections and localization operations.
9591 * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
9592 * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
9593 * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
9594 * 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.
9595 * \param [out] cellIdInMesh1D - the array of pair that gives for each cell id \a i in \a splitMesh1D the cell in \a splitMesh2D on the left for the 1st component
9596 * and the cell in \a splitMesh2D on the right for the 2nt component. -1 means no cell.
9597 * 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.
9599 * \sa Intersect2DMeshes, orderConsecutiveCells1D, conformize2D, mergeNodes
9601 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
9603 if(!mesh2D || !mesh1D)
9604 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
9605 mesh2D->checkFullyDefined();
9606 mesh1D->checkFullyDefined();
9607 const std::vector<std::string>& compNames(mesh2D->getCoords()->getInfoOnComponents());
9608 if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
9609 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
9610 // Step 1: compute all edge intersections (new nodes)
9611 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9612 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
9613 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9614 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9616 // Build desc connectivity
9617 DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
9618 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9619 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
9620 std::map<int,int> mergedNodes;
9621 Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes);
9622 // use mergeNodes to fix intersectEdge1
9623 for(std::vector< std::vector<int> >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++)
9625 std::size_t n((*it0).size()/2);
9626 int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]);
9627 std::map<int,int>::const_iterator it1;
9628 it1=mergedNodes.find(eltStart);
9629 if(it1!=mergedNodes.end())
9630 (*it0)[0]=(*it1).second;
9631 it1=mergedNodes.find(eltEnd);
9632 if(it1!=mergedNodes.end())
9633 (*it0)[2*n-1]=(*it1).second;
9636 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9637 addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9638 // Step 2: re-order newly created nodes according to the ordering found in m2
9639 std::vector< std::vector<int> > intersectEdge2;
9640 BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
9642 // Step 3: compute splitMesh1D
9643 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear;
9644 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2(DataArrayInt::New()); ret2->alloc(0,1);
9645 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1,
9646 idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear));
9647 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(std::numeric_limits<int>::max()); ret3->rearrange(2);
9648 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells()));
9649 // deal with cells in mesh2D that are not cut but only some of their edges are
9650 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCpy());
9651 idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1);
9652 idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique();
9653 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s;//ids in mesh2D that are impacted by the fact that some edges of \a mesh1D are part of the edges of those cells
9654 if(!idsInDesc2DToBeRefined->empty())
9656 DataArrayInt *out0(0),*outi0(0);
9657 MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
9658 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> outi0s(outi0);
9660 out0s=out0s->buildUnique();
9664 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1NonCol(static_cast<MEDCouplingUMesh *>(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end())));
9665 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> baryRet1(ret1NonCol->getBarycenterAndOwner());
9666 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elts,eltsIndex;
9667 mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
9668 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex2(eltsIndex->deltaShiftIndex());
9669 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex3(eltsIndex2->getIdsEqual(1));
9670 if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells())
9671 throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !");
9672 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToBeModified(elts->buildUnique());
9673 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells()));
9674 if((DataArrayInt *)out0s)
9675 untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one
9676 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > outMesh2DSplit;
9677 // OK all is ready to insert in ret2 mesh
9678 if(!untouchedCells->empty())
9679 {// the most easy part, cells in mesh2D not impacted at all
9680 outMesh2DSplit.push_back(static_cast<MEDCouplingUMesh *>(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end())));
9681 outMesh2DSplit.back()->setCoords(ret1->getCoords());
9682 ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end());
9684 if((DataArrayInt *)out0s)
9685 {// here dealing with cells in out0s but not in cellsToBeModified
9686 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fewModifiedCells(out0s->buildSubstraction(cellsToBeModified));
9687 const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin());
9688 for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++)
9690 outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),mesh2D,*it,dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1));
9691 ret1->setCoords(outMesh2DSplit.back()->getCoords());
9693 int offset(ret2->getNumberOfTuples());
9694 ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end());
9695 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1);
9696 partOfRet3->fillWithValue(std::numeric_limits<int>::max()); partOfRet3->rearrange(2);
9697 int kk(0),*ret3ptr(partOfRet3->getPointer());
9698 for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++)
9700 int faceId(std::abs(*it)-1);
9701 for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++)
9703 int tmp(fewModifiedCells->locateValue(*it2));
9706 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9707 ret3ptr[2*kk]=tmp+offset;
9708 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9709 ret3ptr[2*kk+1]=tmp+offset;
9712 {//the current edge is shared by a 2D cell that will be split just after
9713 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9714 ret3ptr[2*kk]=-(*it2+1);
9715 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9716 ret3ptr[2*kk+1]=-(*it2+1);
9720 m1Desc->setCoords(ret1->getCoords());
9721 ret1NonCol->setCoords(ret1->getCoords());
9722 ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true);
9723 if(!outMesh2DSplit.empty())
9725 DataArrayDouble *da(outMesh2DSplit.back()->getCoords());
9726 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> >::iterator itt=outMesh2DSplit.begin();itt!=outMesh2DSplit.end();itt++)
9727 (*itt)->setCoords(da);
9730 cellsToBeModified=cellsToBeModified->buildUniqueNotSorted();
9731 for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++)
9733 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell(elts->getIdsEqual(*it));
9734 idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end());
9735 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end()));
9736 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfMesh1CuttingCur2DCell(static_cast<MEDCouplingUMesh *>(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end())));
9737 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3;
9738 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> splitOfOneCell(BuildMesh2DCutFrom(eps,*it,m1Desc,partOfMesh1CuttingCur2DCell,dd1->begin()+dd2->getIJ(*it,0),dd1->begin()+dd2->getIJ((*it)+1,0),intersectEdge1,ret2->getNumberOfTuples(),partOfRet3));
9739 ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true);
9740 outMesh2DSplit.push_back(splitOfOneCell);
9741 for(int i=0;i<splitOfOneCell->getNumberOfCells();i++)
9742 ret2->pushBackSilent(*it);
9745 std::size_t nbOfMeshes(outMesh2DSplit.size());
9746 std::vector<const MEDCouplingUMesh *> tmp(nbOfMeshes);
9747 for(std::size_t i=0;i<nbOfMeshes;i++)
9748 tmp[i]=outMesh2DSplit[i];
9750 ret1->getCoords()->setInfoOnComponents(compNames);
9751 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2D(MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp));
9752 // To finish - filter ret3 - std::numeric_limits<int>::max() -> -1 - negate values must be resolved.
9754 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> edgesToDealWith(ret3->getIdsStrictlyNegative());
9755 for(const int *it=edgesToDealWith->begin();it!=edgesToDealWith->end();it++)
9757 int old2DCellId(-ret3->getIJ(*it,0)-1);
9758 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates(ret2->getIdsEqual(old2DCellId));
9759 ret3->setIJ(*it,0,FindRightCandidateAmong(ret2D,candidates->begin(),candidates->end(),ret1,*it%2==0?-((*it)/2+1):(*it)/2+1,eps));// div by 2 because 2 components natively in ret3
9761 ret3->replaceOneValByInThis(std::numeric_limits<int>::max(),-1);
9764 splitMesh1D=ret1.retn();
9765 splitMesh2D=ret2D.retn();
9766 cellIdInMesh2D=ret2.retn();
9767 cellIdInMesh1D=ret3.retn();
9771 * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
9772 * (newly created) nodes corresponding to the edge intersections.
9774 * @param[out] cr, crI connectivity of the resulting mesh
9775 * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
9776 * TODO: describe input parameters
9778 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
9779 const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
9780 const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
9781 const std::vector<double>& addCoords,
9782 std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
9784 static const int SPACEDIM=2;
9785 const double *coo1(m1->getCoords()->getConstPointer());
9786 const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer());
9787 int offset1(m1->getNumberOfNodes());
9788 const double *coo2(m2->getCoords()->getConstPointer());
9789 const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer());
9790 int offset2(offset1+m2->getNumberOfNodes());
9791 int offset3(offset2+((int)addCoords.size())/2);
9792 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
9793 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9794 // Here a BBTree on 2D-cells, not on segments:
9795 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
9796 int ncell1(m1->getNumberOfCells());
9798 for(int i=0;i<ncell1;i++)
9800 std::vector<int> candidates2;
9801 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9802 std::map<INTERP_KERNEL::Node *,int> mapp;
9803 std::map<int,INTERP_KERNEL::Node *> mappRev;
9804 INTERP_KERNEL::QuadraticPolygon pol1;
9805 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
9806 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
9807 // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
9808 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
9809 // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
9810 pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
9811 desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
9813 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
9814 std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
9815 INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
9816 for(it1.first();!it1.finished();it1.next())
9817 edges1.insert(it1.current()->getPtr());
9819 std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
9820 std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
9822 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9824 INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
9825 const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
9826 // Complete mapping with elements coming from the current cell it2 in mesh2:
9827 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
9828 // pol2 is the new QP in the final merged result.
9829 pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
9830 pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
9833 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9835 INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
9836 pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
9837 //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
9838 pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9840 // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
9841 // by m2 but that we still want to keep in the final result.
9846 INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9848 catch(INTERP_KERNEL::Exception& e)
9850 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();
9851 throw INTERP_KERNEL::Exception(oss.str().c_str());
9854 for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
9855 (*it).second->decrRef();
9860 * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
9861 * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
9862 * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
9863 * The caller is to deal with the resulting DataArrayInt.
9864 * \throw If the coordinate array is not set.
9865 * \throw If the nodal connectivity of the cells is not defined.
9866 * \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
9867 * \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
9869 * \sa DataArrayInt::sortEachPairToMakeALinkedList
9871 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
9873 checkFullyDefined();
9874 if(getMeshDimension()!=1)
9875 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
9877 // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
9878 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
9879 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
9880 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
9881 const int *d(_d->getConstPointer()), *dI(_dI->getConstPointer());
9882 const int *rD(_rD->getConstPointer()), *rDI(_rDI->getConstPointer());
9883 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
9884 const int * dsi(_dsi->getConstPointer());
9885 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dsii = _dsi->getIdsNotInRange(0,3);
9887 if (dsii->getNumberOfTuples())
9888 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
9890 int nc(getNumberOfCells());
9891 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> result(DataArrayInt::New());
9892 result->alloc(nc,1);
9894 // set of edges not used so far
9895 std::set<int> edgeSet;
9896 for (int i=0; i<nc; edgeSet.insert(i), i++);
9900 // while we have points with only one neighbor segments
9903 std::list<int> linePiece;
9904 // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
9905 for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
9907 // Fill the list forward (resp. backward) from the start segment:
9908 int activeSeg = startSeg;
9909 int prevPointId = -20;
9911 while (!edgeSet.empty())
9913 if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
9916 linePiece.push_back(activeSeg);
9918 linePiece.push_front(activeSeg);
9919 edgeSet.erase(activeSeg);
9922 int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
9923 ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
9924 if (dsi[ptId] == 1) // hitting the end of the line
9927 int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
9928 activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
9931 // Done, save final piece into DA:
9932 std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
9933 newIdx += linePiece.size();
9935 // identify next valid start segment (one which is not consumed)
9936 if(!edgeSet.empty())
9937 startSeg = *(edgeSet.begin());
9939 while (!edgeSet.empty());
9940 return result.retn();
9945 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
9947 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> nTmp(n); nTmp->incrRef();
9948 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>::const_iterator it(m.find(nTmp));
9950 throw INTERP_KERNEL::Exception("Internal error in remapping !");
9951 int v((*it).second);
9952 if(v==forbVal0 || v==forbVal1)
9954 if(std::find(isect.begin(),isect.end(),v)==isect.end())
9958 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
9963 bool presenceOfOn(false);
9964 for(int i=0;i<sz;i++)
9966 INTERP_KERNEL::ElementaryEdge *e(c[i]);
9967 if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
9969 IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
9970 IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
9972 return presenceOfOn;
9978 * 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.
9979 * 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.
9980 * 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.
9981 * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to avoid to have a non conform mesh.
9983 * \return int - the number of new nodes created (in most of cases 0).
9985 * \throw If \a this is not coherent.
9986 * \throw If \a this has not spaceDim equal to 2.
9987 * \throw If \a this has not meshDim equal to 2.
9988 * \throw If some subcells needed to be split are orphan.
9989 * \sa MEDCouplingUMesh::conformize2D
9991 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
9993 if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
9994 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
9995 desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
9996 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
9997 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
9998 if(midOpt==0 && midOptI==0)
10000 split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
10003 else if(midOpt!=0 && midOptI!=0)
10004 return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
10006 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
10010 * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
10011 * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
10012 * 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
10013 * 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).
10014 * 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.
10016 * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
10017 * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
10019 * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
10020 * This method expects that all nodes in \a this are not closer than \a eps.
10021 * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
10023 * \param [in] eps the relative error to detect merged edges.
10024 * \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
10025 * that the user is expected to deal with.
10027 * \throw If \a this is not coherent.
10028 * \throw If \a this has not spaceDim equal to 2.
10029 * \throw If \a this has not meshDim equal to 2.
10030 * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
10032 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
10034 static const int SPACEDIM=2;
10036 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10037 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10038 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
10039 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
10040 const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
10041 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
10042 const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
10043 int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
10044 std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
10045 std::vector<double> addCoo;
10046 BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
10047 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10048 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10049 for(int i=0;i<nDescCell;i++)
10051 std::vector<int> candidates;
10052 myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
10053 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
10056 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10057 INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
10058 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
10059 INTERP_KERNEL::MergePoints merge;
10060 INTERP_KERNEL::QuadraticPolygon c1,c2;
10061 e1->intersectWith(e2,merge,c1,c2);
10062 e1->decrRef(); e2->decrRef();
10063 if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
10064 overlapEdge[i].push_back(*it);
10065 if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
10066 overlapEdge[*it].push_back(i);
10069 // splitting done. sort intersect point in intersectEdge.
10070 std::vector< std::vector<int> > middle(nDescCell);
10071 int nbOf2DCellsToBeSplit(0);
10072 bool middleNeedsToBeUsed(false);
10073 std::vector<bool> cells2DToTreat(nDescCell,false);
10074 for(int i=0;i<nDescCell;i++)
10076 std::vector<int>& isect(intersectEdge[i]);
10077 int sz((int)isect.size());
10080 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10081 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
10082 e->sortSubNodesAbs(coords,isect);
10087 int idx0(rdi[i]),idx1(rdi[i+1]);
10089 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
10090 if(!cells2DToTreat[rd[idx0]])
10092 cells2DToTreat[rd[idx0]]=true;
10093 nbOf2DCellsToBeSplit++;
10095 // try to reuse at most eventual 'middle' of SEG3
10096 std::vector<int>& mid(middle[i]);
10097 mid.resize(sz+1,-1);
10098 if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
10100 middleNeedsToBeUsed=true;
10101 const std::vector<int>& candidates(overlapEdge[i]);
10102 std::vector<int> trueCandidates;
10103 for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
10104 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
10105 trueCandidates.push_back(*itc);
10106 int stNode(c[ci[i]+1]),endNode(isect[0]);
10107 for(int j=0;j<sz+1;j++)
10109 for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
10111 int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
10112 if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
10113 { mid[j]=*itc; break; }
10116 endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
10121 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
10122 if(nbOf2DCellsToBeSplit==0)
10125 int *retPtr(ret->getPointer());
10126 for(int i=0;i<nCell;i++)
10127 if(cells2DToTreat[i])
10130 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
10131 DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
10132 MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
10133 DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
10134 if(middleNeedsToBeUsed)
10135 { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
10136 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
10137 int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
10138 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.
10139 setPartOfMySelf(ret->begin(),ret->end(),*modif);
10141 bool areNodesMerged; int newNbOfNodes;
10142 if(nbOfNodesCreated!=0)
10143 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
10149 * 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.
10150 * 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).
10151 * 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
10152 * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
10153 * 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
10154 * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
10156 * 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
10157 * using new instance, idem for coordinates.
10159 * 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.
10161 * \return DataArrayInt * - The list of cellIds in \a this that have at least one edge colinearized.
10163 * \throw If \a this is not coherent.
10164 * \throw If \a this has not spaceDim equal to 2.
10165 * \throw If \a this has not meshDim equal to 2.
10167 * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
10169 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
10171 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
10173 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10174 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10175 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10176 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10177 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
10178 const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
10179 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
10180 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
10181 const double *coords(_coords->begin());
10182 int *newciptr(newci->getPointer());
10183 for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
10185 if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
10186 ret->pushBackSilent(i);
10187 newciptr[1]=newc->getNumberOfTuples();
10192 if(!appendedCoords->empty())
10194 appendedCoords->rearrange(2);
10195 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
10197 setCoords(newCoords);
10200 setConnectivity(newc,newci,true);
10205 * \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.
10206 * 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.
10207 * And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
10208 * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
10209 * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
10210 * \param [out] addCoo - nodes to be append at the end
10211 * \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.
10213 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
10214 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)
10216 static const int SPACEDIM=2;
10217 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10218 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10219 const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer());
10220 // Build BB tree of all edges in the tool mesh (second mesh)
10221 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
10222 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10223 int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
10224 intersectEdge1.resize(nDescCell1);
10225 colinear2.resize(nDescCell2);
10226 subDiv2.resize(nDescCell2);
10227 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
10229 std::vector<int> candidates1(1);
10230 int offset1(m1Desc->getNumberOfNodes());
10231 int offset2(offset1+m2Desc->getNumberOfNodes());
10232 for(int i=0;i<nDescCell1;i++) // for all edges in the first mesh
10234 std::vector<int> candidates2; // edges of mesh2 candidate for intersection
10235 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10236 if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
10238 std::map<INTERP_KERNEL::Node *,int> map1,map2;
10239 // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
10240 INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
10242 INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
10243 // 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
10244 // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
10245 std::set<INTERP_KERNEL::Node *> nodes;
10246 pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
10247 std::size_t szz(nodes.size());
10248 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
10249 std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
10250 for(std::size_t iii=0;iii<szz;iii++,itt++)
10251 { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
10252 // end of protection
10253 // Performs egde cutting:
10254 pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes);
10259 // Copy the edge (take only the two first points, ie discard quadratic point at this stage)
10260 intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i]+3);
10265 * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
10266 * It builds the descending connectivity of the two meshes, and then using a binary tree
10267 * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
10268 * Documentation about parameters colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
10270 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
10271 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
10272 MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
10273 std::vector<double>& addCoo,
10274 MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
10276 // Build desc connectivity
10277 desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
10278 desc2=DataArrayInt::New();
10279 descIndx2=DataArrayInt::New();
10280 revDesc2=DataArrayInt::New();
10281 revDescIndx2=DataArrayInt::New();
10282 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
10283 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
10284 m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
10285 m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
10286 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
10287 std::map<int,int> notUsedMap;
10288 Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap);
10289 m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
10290 m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
10294 * This method performs the 2nd step of Partition of 2D mesh.
10295 * This method has 4 inputs :
10296 * - a mesh 'm1' with meshDim==1 and a SpaceDim==2
10297 * - a mesh 'm2' with meshDim==1 and a SpaceDim==2
10298 * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
10299 * 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'
10300 * Nodes end up lying consecutively on a cutted edge.
10301 * \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.
10302 * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
10303 * \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.
10304 * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
10305 * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
10307 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
10308 const std::vector<double>& addCoo,
10309 const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
10311 int offset1=m1->getNumberOfNodes();
10312 int ncell=m2->getNumberOfCells();
10313 const int *c=m2->getNodalConnectivity()->getConstPointer();
10314 const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
10315 const double *coo=m2->getCoords()->getConstPointer();
10316 const double *cooBis=m1->getCoords()->getConstPointer();
10317 int offset2=offset1+m2->getNumberOfNodes();
10318 intersectEdge.resize(ncell);
10319 for(int i=0;i<ncell;i++,cI++)
10321 const std::vector<int>& divs=subDiv[i];
10322 int nnode=cI[1]-cI[0]-1;
10323 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
10324 std::map<INTERP_KERNEL::Node *, int> mapp22;
10325 for(int j=0;j<nnode;j++)
10327 INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
10328 int nnid=c[(*cI)+j+1];
10329 mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
10330 mapp22[nn]=nnid+offset1;
10332 INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
10333 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
10334 ((*it).second.first)->decrRef();
10335 std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
10336 std::map<INTERP_KERNEL::Node *,int> mapp3;
10337 for(std::size_t j=0;j<divs.size();j++)
10340 INTERP_KERNEL::Node *tmp=0;
10342 tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
10343 else if(id<offset2)
10344 tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
10346 tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
10350 e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
10351 for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
10358 * 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).
10359 * 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
10360 * with a plane. The result will be put in 'cut3DSuf' out parameter.
10361 * \param [in] cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
10362 * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
10363 * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
10364 * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
10365 * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
10366 * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
10367 * \param [in] desc is the descending connectivity 3DSurf->3DCurve
10368 * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
10369 * \param [out] cut3DSuf input/output param.
10371 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
10372 const int *nodal3DCurve, const int *nodalIndx3DCurve,
10373 const int *desc, const int *descIndx,
10374 std::vector< std::pair<int,int> >& cut3DSurf)
10376 std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
10377 int nbOf3DSurfCell=(int)cut3DSurf.size();
10378 for(int i=0;i<nbOf3DSurfCell;i++)
10380 std::vector<int> res;
10381 int offset=descIndx[i];
10382 int nbOfSeg=descIndx[i+1]-offset;
10383 for(int j=0;j<nbOfSeg;j++)
10385 int edgeId=desc[offset+j];
10386 int status=cut3DCurve[edgeId];
10390 res.push_back(status);
10393 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
10394 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
10402 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10408 std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
10409 std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
10412 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10416 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
10421 {// case when plane is on a multi colinear edge of a polyhedron
10422 if((int)res.size()==2*nbOfSeg)
10424 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
10427 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
10434 * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
10435 * 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).
10436 * 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
10437 * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
10438 * \param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
10439 * \param desc is the descending connectivity 3D->3DSurf
10440 * \param descIndx is the descending connectivity index 3D->3DSurf
10442 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
10443 const int *desc, const int *descIndx,
10444 DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
10446 checkFullyDefined();
10447 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10448 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
10449 const int *nodal3D=_nodal_connec->getConstPointer();
10450 const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
10451 int nbOfCells=getNumberOfCells();
10452 for(int i=0;i<nbOfCells;i++)
10454 std::map<int, std::set<int> > m;
10455 int offset=descIndx[i];
10456 int nbOfFaces=descIndx[i+1]-offset;
10459 for(int j=0;j<nbOfFaces;j++)
10461 const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
10462 if(p.first!=-1 && p.second!=-1)
10466 start=p.first; end=p.second;
10467 m[p.first].insert(p.second);
10468 m[p.second].insert(p.first);
10472 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
10473 int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
10474 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
10475 INTERP_KERNEL::NormalizedCellType cmsId;
10476 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
10477 start=tmp[0]; end=tmp[nbOfNodesSon-1];
10478 for(unsigned k=0;k<nbOfNodesSon;k++)
10480 m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
10481 m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
10488 std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
10492 std::map<int, std::set<int> >::const_iterator it=m.find(start);
10493 const std::set<int>& s=(*it).second;
10494 std::set<int> s2; s2.insert(prev);
10496 std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
10499 int val=*s3.begin();
10500 conn.push_back(start);
10507 conn.push_back(end);
10510 nodalRes->insertAtTheEnd(conn.begin(),conn.end());
10511 nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
10512 cellIds->pushBackSilent(i);
10518 * 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
10519 * 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
10520 * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
10521 * 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
10522 * 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.
10524 * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
10526 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
10528 std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
10531 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
10532 if(cm.getDimension()==2)
10534 const int *node=nodalConnBg+1;
10535 int startNode=*node++;
10536 double refX=coords[2*startNode];
10537 for(;node!=nodalConnEnd;node++)
10539 if(coords[2*(*node)]<refX)
10542 refX=coords[2*startNode];
10545 std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
10549 double angle0=-M_PI/2;
10554 double angleNext=0.;
10555 while(nextNode!=startNode)
10559 for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
10561 if(*node!=tmpOut.back() && *node!=prevNode)
10563 tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
10564 double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
10569 res=angle0-angleM+2.*M_PI;
10578 if(nextNode!=startNode)
10580 angle0=angleNext-M_PI;
10583 prevNode=tmpOut.back();
10584 tmpOut.push_back(nextNode);
10587 std::vector<int> tmp3(2*(sz-1));
10588 std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
10589 std::copy(nodalConnBg+1,nodalConnEnd,it);
10590 if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
10592 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10595 if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
10597 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10602 nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
10603 nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
10608 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10611 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10615 * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
10616 * 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.
10618 * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
10619 * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
10620 * \param [in,out] arr array in which the remove operation will be done.
10621 * \param [in,out] arrIndx array in the remove operation will modify
10622 * \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])
10623 * \return true if \b arr and \b arrIndx have been modified, false if not.
10625 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
10627 if(!arrIndx || !arr)
10628 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
10629 if(offsetForRemoval<0)
10630 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
10631 std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
10632 int nbOfGrps=arrIndx->getNumberOfTuples()-1;
10633 int *arrIPtr=arrIndx->getPointer();
10635 int previousArrI=0;
10636 const int *arrPtr=arr->getConstPointer();
10637 std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
10638 for(int i=0;i<nbOfGrps;i++,arrIPtr++)
10640 if(*arrIPtr-previousArrI>offsetForRemoval)
10642 for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
10644 if(s.find(*work)==s.end())
10645 arrOut.push_back(*work);
10648 previousArrI=*arrIPtr;
10649 *arrIPtr=(int)arrOut.size();
10651 if(arr->getNumberOfTuples()==(int)arrOut.size())
10653 arr->alloc((int)arrOut.size(),1);
10654 std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
10659 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10660 * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
10661 * The selection of extraction is done standardly in new2old format.
10662 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10664 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10665 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10666 * \param [in] arrIn arr origin array from which the extraction will be done.
10667 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10668 * \param [out] arrOut the resulting array
10669 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10670 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
10672 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10673 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10675 if(!arrIn || !arrIndxIn)
10676 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
10677 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10678 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10679 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
10680 std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
10681 const int *arrInPtr=arrIn->getConstPointer();
10682 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10683 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10685 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10686 int maxSizeOfArr=arrIn->getNumberOfTuples();
10687 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10688 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10689 arrIo->alloc((int)(sz+1),1);
10690 const int *idsIt=idsOfSelectBg;
10691 int *work=arrIo->getPointer();
10694 for(std::size_t i=0;i<sz;i++,work++,idsIt++)
10696 if(*idsIt>=0 && *idsIt<nbOfGrps)
10697 lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
10700 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10701 throw INTERP_KERNEL::Exception(oss.str().c_str());
10707 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
10708 oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
10709 throw INTERP_KERNEL::Exception(oss.str().c_str());
10712 arro->alloc(lgth,1);
10713 work=arro->getPointer();
10714 idsIt=idsOfSelectBg;
10715 for(std::size_t i=0;i<sz;i++,idsIt++)
10717 if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
10718 work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
10721 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
10722 oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10723 throw INTERP_KERNEL::Exception(oss.str().c_str());
10726 arrOut=arro.retn();
10727 arrIndexOut=arrIo.retn();
10731 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10732 * 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 ).
10733 * The selection of extraction is done standardly in new2old format.
10734 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10736 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10737 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10738 * \param [in] arrIn arr origin array from which the extraction will be done.
10739 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10740 * \param [out] arrOut the resulting array
10741 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10742 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
10744 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10745 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10747 if(!arrIn || !arrIndxIn)
10748 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
10749 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10750 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10751 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
10752 int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
10753 const int *arrInPtr=arrIn->getConstPointer();
10754 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10755 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10757 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10758 int maxSizeOfArr=arrIn->getNumberOfTuples();
10759 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10760 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10761 arrIo->alloc((int)(sz+1),1);
10762 int idsIt=idsOfSelectStart;
10763 int *work=arrIo->getPointer();
10766 for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
10768 if(idsIt>=0 && idsIt<nbOfGrps)
10769 lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
10772 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10773 throw INTERP_KERNEL::Exception(oss.str().c_str());
10779 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
10780 oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
10781 throw INTERP_KERNEL::Exception(oss.str().c_str());
10784 arro->alloc(lgth,1);
10785 work=arro->getPointer();
10786 idsIt=idsOfSelectStart;
10787 for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
10789 if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
10790 work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
10793 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
10794 oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10795 throw INTERP_KERNEL::Exception(oss.str().c_str());
10798 arrOut=arro.retn();
10799 arrIndexOut=arrIo.retn();
10803 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10804 * 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
10805 * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
10806 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
10808 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10809 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10810 * \param [in] arrIn arr origin array from which the extraction will be done.
10811 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10812 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
10813 * \param [in] srcArrIndex index array of \b srcArr
10814 * \param [out] arrOut the resulting array
10815 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10817 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
10819 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10820 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
10821 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10823 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10824 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
10825 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10826 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10827 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10828 std::vector<bool> v(nbOfTuples,true);
10830 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10831 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10832 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10834 if(*it>=0 && *it<nbOfTuples)
10837 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
10841 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
10842 throw INTERP_KERNEL::Exception(oss.str().c_str());
10845 srcArrIndexPtr=srcArrIndex->getConstPointer();
10846 arrIo->alloc(nbOfTuples+1,1);
10847 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
10848 const int *arrInPtr=arrIn->getConstPointer();
10849 const int *srcArrPtr=srcArr->getConstPointer();
10850 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
10851 int *arroPtr=arro->getPointer();
10852 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
10856 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
10857 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
10861 std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
10862 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
10863 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
10866 arrOut=arro.retn();
10867 arrIndexOut=arrIo.retn();
10871 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10872 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
10874 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10875 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10876 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
10877 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10878 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
10879 * \param [in] srcArrIndex index array of \b srcArr
10881 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
10883 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
10884 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
10886 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10887 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
10888 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10889 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10890 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10891 int *arrInOutPtr=arrInOut->getPointer();
10892 const int *srcArrPtr=srcArr->getConstPointer();
10893 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10895 if(*it>=0 && *it<nbOfTuples)
10897 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
10898 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
10901 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] !";
10902 throw INTERP_KERNEL::Exception(oss.str().c_str());
10907 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
10908 throw INTERP_KERNEL::Exception(oss.str().c_str());
10914 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
10915 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
10916 * 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]].
10917 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
10918 * A negative value in \b arrIn means that it is ignored.
10919 * 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.
10921 * \param [in] arrIn arr origin array from which the extraction will be done.
10922 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10923 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
10924 * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
10926 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
10928 int seed=0,nbOfDepthPeelingPerformed=0;
10929 return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
10933 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
10934 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
10935 * 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]].
10936 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
10937 * A negative value in \b arrIn means that it is ignored.
10938 * 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.
10939 * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
10940 * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
10941 * \param [in] arrIn arr origin array from which the extraction will be done.
10942 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10943 * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
10944 * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
10945 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
10946 * \sa MEDCouplingUMesh::partitionBySpreadZone
10948 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
10950 nbOfDepthPeelingPerformed=0;
10952 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
10953 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10956 DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
10960 std::vector<bool> fetched(nbOfTuples,false);
10961 return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
10964 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
10966 nbOfDepthPeelingPerformed=0;
10967 if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
10968 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
10969 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10970 std::vector<bool> fetched2(nbOfTuples,false);
10972 for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
10974 if(*seedElt>=0 && *seedElt<nbOfTuples)
10975 { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
10977 { 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()); }
10979 const int *arrInPtr=arrIn->getConstPointer();
10980 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10981 int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
10982 std::vector<int> idsToFetch1(seedBg,seedEnd);
10983 std::vector<int> idsToFetch2;
10984 std::vector<int> *idsToFetch=&idsToFetch1;
10985 std::vector<int> *idsToFetchOther=&idsToFetch2;
10986 while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
10988 for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
10989 for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
10991 { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
10992 std::swap(idsToFetch,idsToFetchOther);
10993 idsToFetchOther->clear();
10994 nbOfDepthPeelingPerformed++;
10996 int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
10998 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
10999 int *retPtr=ret->getPointer();
11000 for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
11007 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11008 * 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
11009 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11010 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11012 * \param [in] start begin of set of ids of the input extraction (included)
11013 * \param [in] end end of set of ids of the input extraction (excluded)
11014 * \param [in] step step of the set of ids in range mode.
11015 * \param [in] arrIn arr origin array from which the extraction will be done.
11016 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11017 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11018 * \param [in] srcArrIndex index array of \b srcArr
11019 * \param [out] arrOut the resulting array
11020 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11022 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
11024 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11025 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11026 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11028 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11029 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
11030 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
11031 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
11032 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11034 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11035 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11036 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
11038 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11040 if(it>=0 && it<nbOfTuples)
11041 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
11044 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11045 throw INTERP_KERNEL::Exception(oss.str().c_str());
11048 srcArrIndexPtr=srcArrIndex->getConstPointer();
11049 arrIo->alloc(nbOfTuples+1,1);
11050 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11051 const int *arrInPtr=arrIn->getConstPointer();
11052 const int *srcArrPtr=srcArr->getConstPointer();
11053 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11054 int *arroPtr=arro->getPointer();
11055 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11057 int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
11060 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11061 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11065 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11066 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11069 arrOut=arro.retn();
11070 arrIndexOut=arrIo.retn();
11074 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11075 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11077 * \param [in] start begin of set of ids of the input extraction (included)
11078 * \param [in] end end of set of ids of the input extraction (excluded)
11079 * \param [in] step step of the set of ids in range mode.
11080 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11081 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11082 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11083 * \param [in] srcArrIndex index array of \b srcArr
11085 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11087 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11088 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11090 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11091 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
11092 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11093 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11094 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11095 int *arrInOutPtr=arrInOut->getPointer();
11096 const int *srcArrPtr=srcArr->getConstPointer();
11097 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
11099 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11101 if(it>=0 && it<nbOfTuples)
11103 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
11104 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
11107 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
11108 throw INTERP_KERNEL::Exception(oss.str().c_str());
11113 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11114 throw INTERP_KERNEL::Exception(oss.str().c_str());
11120 * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
11121 * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
11122 * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
11123 * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
11124 * The sum of measure field of returned mesh is equal to the sum of measure field of this.
11126 * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
11128 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
11130 checkFullyDefined();
11131 int mdim=getMeshDimension();
11132 int spaceDim=getSpaceDimension();
11134 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
11135 std::vector<DataArrayInt *> partition=partitionBySpreadZone();
11136 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
11137 std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
11138 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
11139 ret->setCoords(getCoords());
11140 ret->allocateCells((int)partition.size());
11142 for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
11144 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
11145 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
11149 cell=tmp->buildUnionOf2DMesh();
11152 cell=tmp->buildUnionOf3DMesh();
11155 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
11158 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
11161 ret->finishInsertingCells();
11166 * This method partitions \b this into contiguous zone.
11167 * This method only needs a well defined connectivity. Coordinates are not considered here.
11168 * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
11170 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
11172 int nbOfCellsCur=getNumberOfCells();
11173 std::vector<DataArrayInt *> ret;
11174 if(nbOfCellsCur<=0)
11176 DataArrayInt *neigh=0,*neighI=0;
11177 computeNeighborsOfCells(neigh,neighI);
11178 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
11179 std::vector<bool> fetchedCells(nbOfCellsCur,false);
11180 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
11182 while(seed<nbOfCellsCur)
11184 int nbOfPeelPerformed=0;
11185 ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
11186 seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
11188 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
11189 ret.push_back((*it).retn());
11194 * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
11195 * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
11197 * \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.
11198 * \return a newly allocated DataArrayInt to be managed by the caller.
11199 * \throw In case of \a code has not the right format (typically of size 3*n)
11201 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
11203 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
11204 std::size_t nb=code.size()/3;
11205 if(code.size()%3!=0)
11206 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
11207 ret->alloc((int)nb,2);
11208 int *retPtr=ret->getPointer();
11209 for(std::size_t i=0;i<nb;i++,retPtr+=2)
11211 retPtr[0]=code[3*i+2];
11212 retPtr[1]=code[3*i+2]+code[3*i+1];
11218 * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
11219 * All cells in \a this are expected to be linear 3D cells.
11220 * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
11221 * It leads to an increase to number of cells.
11222 * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
11223 * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints
11224 * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
11226 * \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.
11227 * For all other cells, the splitting policy will be ignored.
11228 * \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.
11229 * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
11230 * an id of old cell producing it. The caller is to delete this array using
11231 * decrRef() as it is no more needed.
11232 * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
11234 * \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
11235 * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
11237 * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
11238 * \throw If \a this is not fully constituted with linear 3D cells.
11239 * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
11241 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
11243 INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
11244 checkConnectivityFullyDefined();
11245 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
11246 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
11247 int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
11248 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
11249 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
11250 int *retPt(ret->getPointer());
11251 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
11252 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
11253 const int *oldc(_nodal_connec->begin());
11254 const int *oldci(_nodal_connec_index->begin());
11255 const double *coords(_coords->begin());
11256 for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
11258 std::vector<int> a; std::vector<double> b;
11259 INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
11260 std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
11261 const int *aa(&a[0]);
11264 for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
11266 *it=(-(*(it))-1+nbNodes);
11267 addPts->insertAtTheEnd(b.begin(),b.end());
11268 nbNodes+=(int)b.size()/3;
11270 for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
11271 newConn->insertAtTheEnd(aa,aa+4);
11273 if(!addPts->empty())
11275 addPts->rearrange(3);
11276 nbOfAdditionalPoints=addPts->getNumberOfTuples();
11277 addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
11278 ret0->setCoords(addPts);
11282 nbOfAdditionalPoints=0;
11283 ret0->setCoords(getCoords());
11285 ret0->setNodalConnectivity(newConn);
11287 ret->computeOffsets2();
11288 n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
11289 return ret0.retn();
11293 * 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).
11295 * \sa MEDCouplingUMesh::split2DCells
11297 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
11299 checkConnectivityFullyDefined();
11300 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
11301 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11302 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11303 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11304 int prevPosOfCi(ciPtr[0]);
11305 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11307 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
11308 *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
11309 for(int j=0;j<sz;j++)
11311 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
11312 for(int k=0;k<sz2;k++)
11313 *cPtr++=subPtr[offset2+k];
11315 *cPtr++=oldConn[prevPosOfCi+j+2];
11318 prevPosOfCi=ciPtr[1];
11319 ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11322 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
11323 _nodal_connec->decrRef();
11324 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
11327 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11333 int ret(nodesCnter++);
11335 e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
11336 addCoo.insertAtTheEnd(newPt,newPt+2);
11343 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)
11346 int trueStart(start>=0?start:nbOfEdges+start);
11347 tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
11348 newConnOfCell->insertAtTheEnd(tmp,tmp+3);
11353 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11354 InternalAddPoint(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
11355 middles.push_back(tmp3+offset);
11358 middles.push_back(connBg[trueStart+nbOfEdges]);
11362 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)
11364 int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
11365 newConnOfCell->pushBackSilent(tmpEnd);
11370 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11371 InternalAddPoint(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11372 middles.push_back(tmp3+offset);
11375 middles.push_back(connBg[start+nbOfEdges]);
11379 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)
11385 int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
11386 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11387 InternalAddPoint(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11388 middles.push_back(tmp3+offset);
11391 middles.push_back(connBg[start+nbOfEdges]);
11398 * 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 ) .
11399 * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
11401 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
11403 std::size_t sz(std::distance(connBg,connEnd));
11404 if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
11405 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
11407 INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
11408 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
11409 unsigned nbs(cm.getNumberOfSons2(connBg+1,sz)),nbOfHit(0);
11410 int posBaseElt(0),posEndElt(0),nbOfTurn(0);
11411 INTERP_KERNEL::NormalizedCellType typeOfSon;
11412 std::vector<int> middles;
11414 for(;nbOfHit<nbs;nbOfTurn++)
11416 cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
11417 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
11418 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11421 unsigned endI(nbs-nbOfHit);
11422 for(unsigned i=0;i<endI;i++)
11424 cm.fillSonCellNodalConnectivity2(posBaseElt+(int)i+1,connBg+1,sz,tmpConn,typeOfSon);
11425 INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11426 INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11427 bool isColinear(eint->areColinears());
11439 {//look if the first edge of cell is not colinear with last edges in this case the start of nodal connectivity is shifted back
11440 unsigned endII(nbs-nbOfHit-1);//warning nbOfHit can be modified, so put end condition in a variable.
11441 for(unsigned ii=0;ii<endII;ii++)
11443 cm.fillSonCellNodalConnectivity2(nbs-ii-1,connBg+1,sz,tmpConn,typeOfSon);
11444 eCand=MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m);
11445 eint=INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand);
11446 isColinear=eint->areColinears();
11462 //push [posBaseElt,posEndElt) in newConnOfCell using e
11464 EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11465 else if(nbOfHit!=nbs)
11466 EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11468 EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11469 posBaseElt=posEndElt;
11472 if(!middles.empty())
11473 newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
11478 * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
11480 * \return int - the number of new nodes created.
11481 * \sa MEDCouplingUMesh::split2DCells
11483 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
11486 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
11487 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11488 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
11489 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11490 const int *midPtr(mid->begin()),*midIPtr(midI->begin());
11491 const double *oldCoordsPtr(getCoords()->begin());
11492 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11493 int prevPosOfCi(ciPtr[0]);
11494 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11496 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
11497 for(int j=0;j<sz;j++)
11498 { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
11499 *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
11500 for(int j=0;j<sz;j++)//loop over subedges of oldConn
11502 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
11506 cPtr[1]=oldConn[prevPosOfCi+2+j];
11507 cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
11510 std::vector<INTERP_KERNEL::Node *> ns(3);
11511 ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
11512 ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
11513 ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
11514 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
11515 for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
11517 cPtr[1]=subPtr[offset2+k];
11518 cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
11520 int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
11522 { cPtr[1]=tmpEnd; }
11523 cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
11525 prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
11526 ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11529 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
11530 _nodal_connec->decrRef();
11531 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
11532 addCoo->rearrange(2);
11533 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
11535 return addCoo->getNumberOfTuples();
11538 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
11539 _own_cell(true),_cell_id(-1),_nb_cell(0)
11544 _nb_cell=mesh->getNumberOfCells();
11548 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
11556 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
11557 _own_cell(false),_cell_id(bg-1),
11564 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
11567 if(_cell_id<_nb_cell)
11576 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
11582 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
11584 return new MEDCouplingUMeshCellByTypeIterator(_mesh);
11587 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
11593 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
11601 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
11607 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
11612 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
11617 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
11619 return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
11622 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
11627 _nb_cell=mesh->getNumberOfCells();
11631 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
11638 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
11640 const int *c=_mesh->getNodalConnectivity()->getConstPointer();
11641 const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
11642 if(_cell_id<_nb_cell)
11644 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
11645 int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
11646 int startId=_cell_id;
11647 _cell_id+=nbOfElems;
11648 return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
11654 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
11658 _conn=mesh->getNodalConnectivity()->getPointer();
11659 _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
11663 void MEDCouplingUMeshCell::next()
11665 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11670 _conn_lgth=_conn_indx[1]-_conn_indx[0];
11673 std::string MEDCouplingUMeshCell::repr() const
11675 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11677 std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
11679 std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
11683 return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
11686 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
11688 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11689 return (INTERP_KERNEL::NormalizedCellType)_conn[0];
11691 return INTERP_KERNEL::NORM_ERROR;
11694 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
11697 if(_conn_lgth!=NOTICABLE_FIRST_VAL)