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
1396 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1398 checkConnectivityFullyDefined();
1399 int nbOfCells=getNumberOfCells();
1400 const int *connIndex=_nodal_connec_index->getConstPointer();
1401 const int *conn=_nodal_connec->getConstPointer();
1402 const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1403 int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1404 std::vector<bool> retS(maxElt,false);
1405 for(int i=0;i<nbOfCells;i++)
1406 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1410 for(int i=0;i<maxElt;i++)
1413 DataArrayInt *ret=DataArrayInt::New();
1415 int *retPtr=ret->getPointer();
1416 for(int i=0;i<maxElt;i++)
1423 * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1424 * \sa MEDCouplingUMesh::getNodeIdsInUse
1426 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1428 int nbOfNodes((int)nodeIdsInUse.size()),nbOfCells(getNumberOfCells());
1429 const int *connIndex(_nodal_connec_index->getConstPointer()),*conn(_nodal_connec->getConstPointer());
1430 for(int i=0;i<nbOfCells;i++)
1431 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1434 if(conn[j]<nbOfNodes)
1435 nodeIdsInUse[conn[j]]=true;
1438 std::ostringstream oss; oss << "MEDCouplingUMesh::computeNodeIdsAlg : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1439 throw INTERP_KERNEL::Exception(oss.str().c_str());
1445 * Finds nodes not used in any cell and returns an array giving a new id to every node
1446 * by excluding the unused nodes, for which the array holds -1. The result array is
1447 * a mapping in "Old to New" mode.
1448 * \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1449 * \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1450 * this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1451 * if the node is unused or a new id else. The caller is to delete this
1452 * array using decrRef() as it is no more needed.
1453 * \throw If the coordinates array is not set.
1454 * \throw If the nodal connectivity of cells is not defined.
1455 * \throw If the nodal connectivity includes an invalid id.
1457 * \if ENABLE_EXAMPLES
1458 * \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1459 * \ref py_mcumesh_getNodeIdsInUse "Here is a Python example".
1461 * \sa computeFetchedNodeIds, computeNodeIdsAlg()
1463 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1466 int nbOfNodes(getNumberOfNodes());
1467 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1468 ret->alloc(nbOfNodes,1);
1469 int *traducer=ret->getPointer();
1470 std::fill(traducer,traducer+nbOfNodes,-1);
1471 int nbOfCells=getNumberOfCells();
1472 const int *connIndex=_nodal_connec_index->getConstPointer();
1473 const int *conn=_nodal_connec->getConstPointer();
1474 for(int i=0;i<nbOfCells;i++)
1475 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1478 if(conn[j]<nbOfNodes)
1479 traducer[conn[j]]=1;
1482 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1483 throw INTERP_KERNEL::Exception(oss.str().c_str());
1486 nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1487 std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1492 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1493 * For each cell in \b this the number of nodes constituting cell is computed.
1494 * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1495 * So for pohyhedrons some nodes can be counted several times in the returned result.
1497 * \return a newly allocated array
1498 * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1500 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1502 checkConnectivityFullyDefined();
1503 int nbOfCells=getNumberOfCells();
1504 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1505 ret->alloc(nbOfCells,1);
1506 int *retPtr=ret->getPointer();
1507 const int *conn=getNodalConnectivity()->getConstPointer();
1508 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1509 for(int i=0;i<nbOfCells;i++,retPtr++)
1511 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1512 *retPtr=connI[i+1]-connI[i]-1;
1514 *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1520 * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1521 * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1523 * \return DataArrayInt * - new object to be deallocated by the caller.
1524 * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1526 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1528 checkConnectivityFullyDefined();
1529 int nbOfCells=getNumberOfCells();
1530 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1531 ret->alloc(nbOfCells,1);
1532 int *retPtr=ret->getPointer();
1533 const int *conn=getNodalConnectivity()->getConstPointer();
1534 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1535 for(int i=0;i<nbOfCells;i++,retPtr++)
1537 std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1538 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1539 *retPtr=(int)s.size();
1543 *retPtr=(int)s.size();
1550 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1551 * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1553 * \return a newly allocated array
1555 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1557 checkConnectivityFullyDefined();
1558 int nbOfCells=getNumberOfCells();
1559 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1560 ret->alloc(nbOfCells,1);
1561 int *retPtr=ret->getPointer();
1562 const int *conn=getNodalConnectivity()->getConstPointer();
1563 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1564 for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1566 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1567 *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1573 * Removes unused nodes (the node coordinates array is shorten) and returns an array
1574 * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1575 * array mean that the corresponding old node is no more used.
1576 * \return DataArrayInt * - a new instance of DataArrayInt of length \a
1577 * this->getNumberOfNodes() before call of this method. The caller is to
1578 * delete this array using decrRef() as it is no more needed.
1579 * \throw If the coordinates array is not set.
1580 * \throw If the nodal connectivity of cells is not defined.
1581 * \throw If the nodal connectivity includes an invalid id.
1583 * \if ENABLE_EXAMPLES
1584 * \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1585 * \ref py_mcumesh_zipCoordsTraducer "Here is a Python example".
1588 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1590 return MEDCouplingPointSet::zipCoordsTraducer();
1594 * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1595 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1597 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1602 return AreCellsEqual0(conn,connI,cell1,cell2);
1604 return AreCellsEqual1(conn,connI,cell1,cell2);
1606 return AreCellsEqual2(conn,connI,cell1,cell2);
1608 return AreCellsEqual3(conn,connI,cell1,cell2);
1610 return AreCellsEqual7(conn,connI,cell1,cell2);
1612 throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1616 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1618 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1620 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1621 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1626 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1628 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1630 int sz=connI[cell1+1]-connI[cell1];
1631 if(sz==connI[cell2+1]-connI[cell2])
1633 if(conn[connI[cell1]]==conn[connI[cell2]])
1635 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1636 unsigned dim=cm.getDimension();
1642 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1643 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1644 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1645 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1646 return work!=tmp+sz1?1:0;
1649 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1652 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1659 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1661 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1663 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1665 if(conn[connI[cell1]]==conn[connI[cell2]])
1667 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1668 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1676 * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1678 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1680 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1682 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1683 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1690 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1692 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1694 int sz=connI[cell1+1]-connI[cell1];
1695 if(sz==connI[cell2+1]-connI[cell2])
1697 if(conn[connI[cell1]]==conn[connI[cell2]])
1699 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1700 unsigned dim=cm.getDimension();
1706 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1707 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1708 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1709 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1714 std::reverse_iterator<int *> it1((int *)tmp+sz1);
1715 std::reverse_iterator<int *> it2((int *)tmp);
1716 if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1722 return work!=tmp+sz1?1:0;
1725 {//case of SEG2 and SEG3
1726 if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1728 if(!cm.isQuadratic())
1730 std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1731 std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1732 if(std::equal(it1,it2,conn+connI[cell2]+1))
1738 if(conn[connI[cell1]+1]==conn[connI[cell2]+2] && conn[connI[cell1]+2]==conn[connI[cell2]+1] && conn[connI[cell1]+3]==conn[connI[cell2]+3])
1745 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1752 * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1753 * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1754 * and result remains unchanged.
1755 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1756 * If in 'candidates' pool -1 value is considered as an empty value.
1757 * WARNING this method returns only ONE set of result !
1759 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1761 if(candidates.size()<1)
1764 std::vector<int>::const_iterator iter=candidates.begin();
1765 int start=(*iter++);
1766 for(;iter!=candidates.end();iter++)
1768 int status=AreCellsEqual(conn,connI,start,*iter,compType);
1773 result->pushBackSilent(start);
1777 result->pushBackSilent(*iter);
1779 result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1786 * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1787 * This method keeps the coordiantes of \a this. This method is time consuming and is called
1789 * \param [in] compType input specifying the technique used to compare cells each other.
1790 * - 0 : exactly. A cell is detected to be the same if and only if the connectivity is exactly the same without permutation and types same too. This is the strongest policy.
1791 * - 1 : permutation same orientation. cell1 and cell2 are considered equal if the connectivity of cell2 can be deduced by those of cell1 by direct permutation (with exactly the same orientation)
1792 * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1793 * - 2 : nodal. cell1 and cell2 are equal if and only if cell1 and cell2 have same type and have the same nodes constituting connectivity. This is the laziest policy. This policy
1794 * can be used for users not sensitive to orientation of cell
1795 * \param [in] startCellId specifies the cellId starting from which the equality computation will be carried out. By default it is 0, which it means that all cells in \a this will be scanned.
1796 * \param [out] commonCells
1797 * \param [out] commonCellsI
1798 * \return the correspondance array old to new in a newly allocated array.
1801 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1803 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1804 getReverseNodalConnectivity(revNodal,revNodalI);
1805 FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1808 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1809 DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr)
1811 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1812 int nbOfCells=nodalI->getNumberOfTuples()-1;
1813 commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1814 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1815 const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1816 std::vector<bool> isFetched(nbOfCells,false);
1819 for(int i=0;i<nbOfCells;i++)
1823 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1824 std::vector<int> v,v2;
1825 if(connOfNode!=connPtr+connIPtr[i+1])
1827 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1828 v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1831 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1835 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1836 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1837 v2.resize(std::distance(v2.begin(),it));
1841 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1843 int pos=commonCellsI->back();
1844 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1845 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1846 isFetched[*it]=true;
1854 for(int i=startCellId;i<nbOfCells;i++)
1858 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1859 std::vector<int> v,v2;
1860 if(connOfNode!=connPtr+connIPtr[i+1])
1862 v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1865 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1869 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1870 v2.resize(std::distance(v2.begin(),it));
1874 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1876 int pos=commonCellsI->back();
1877 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1878 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1879 isFetched[*it]=true;
1885 commonCellsArr=commonCells.retn();
1886 commonCellsIArr=commonCellsI.retn();
1890 * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1891 * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1892 * than \a other->getNumberOfCells() in the returned array means that there is no
1893 * corresponding cell in \a this mesh.
1894 * It is expected that \a this and \a other meshes share the same node coordinates
1895 * array, if it is not so an exception is thrown.
1896 * \param [in] other - the mesh to compare with.
1897 * \param [in] compType - specifies a cell comparison technique. For meaning of its
1898 * valid values [0,1,2], see zipConnectivityTraducer().
1899 * \param [out] arr - a new instance of DataArrayInt returning correspondence
1900 * between cells of the two meshes. It contains \a other->getNumberOfCells()
1901 * values. The caller is to delete this array using
1902 * decrRef() as it is no more needed.
1903 * \return bool - \c true if all cells of \a other mesh are present in the \a this
1906 * \if ENABLE_EXAMPLES
1907 * \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1908 * \ref py_mcumesh_areCellsIncludedIn "Here is a Python example".
1910 * \sa checkDeepEquivalOnSameNodesWith()
1911 * \sa checkGeoEquivalWith()
1913 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1915 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1916 int nbOfCells=getNumberOfCells();
1917 static const int possibleCompType[]={0,1,2};
1918 if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1920 std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1921 std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1923 throw INTERP_KERNEL::Exception(oss.str().c_str());
1925 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1926 arr=o2n->substr(nbOfCells);
1927 arr->setName(other->getName());
1929 if(other->getNumberOfCells()==0)
1931 return arr->getMaxValue(tmp)<nbOfCells;
1935 * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1936 * This method tries to determine if \b other is fully included in \b this.
1937 * The main difference is that this method is not expected to throw exception.
1938 * This method has two outputs :
1940 * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1941 * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1943 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1945 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1946 DataArrayInt *commonCells=0,*commonCellsI=0;
1947 int thisNbCells=getNumberOfCells();
1948 mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1949 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1950 const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1951 int otherNbCells=other->getNumberOfCells();
1952 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1953 arr2->alloc(otherNbCells,1);
1954 arr2->fillWithZero();
1955 int *arr2Ptr=arr2->getPointer();
1956 int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1957 for(int i=0;i<nbOfCommon;i++)
1959 int start=commonCellsPtr[commonCellsIPtr[i]];
1960 if(start<thisNbCells)
1962 for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1964 int sig=commonCellsPtr[j]>0?1:-1;
1965 int val=std::abs(commonCellsPtr[j])-1;
1966 if(val>=thisNbCells)
1967 arr2Ptr[val-thisNbCells]=sig*(start+1);
1971 arr2->setName(other->getName());
1972 if(arr2->presenceOfValue(0))
1978 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1981 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1982 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1984 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1985 std::vector<const MEDCouplingUMesh *> ms(2);
1988 return MergeUMeshesOnSameCoords(ms);
1992 * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1993 * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1994 * cellIds is not given explicitely but by a range python like.
1996 * \param keepCoords that specifies if you want or not to keep coords as this or zip it (see ParaMEDMEM::MEDCouplingUMesh::zipCoords). If true zipCoords is \b NOT called, if false, zipCoords is called.
1997 * \return a newly allocated
1999 * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
2000 * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
2002 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const
2004 if(getMeshDimension()!=-1)
2005 return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
2008 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
2010 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2012 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2014 return const_cast<MEDCouplingUMesh *>(this);
2019 * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
2020 * The result mesh shares or not the node coordinates array with \a this mesh depending
2021 * on \a keepCoords parameter.
2022 * \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
2023 * to write this mesh to the MED file, its cells must be sorted using
2024 * sortCellsInMEDFileFrmt().
2025 * \param [in] begin - an array of cell ids to include to the new mesh.
2026 * \param [in] end - a pointer to last-plus-one-th element of \a begin.
2027 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2028 * array of \a this mesh, else "free" nodes are removed from the result mesh
2029 * by calling zipCoords().
2030 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2031 * to delete this mesh using decrRef() as it is no more needed.
2032 * \throw If the coordinates array is not set.
2033 * \throw If the nodal connectivity of cells is not defined.
2034 * \throw If any cell id in the array \a begin is not valid.
2036 * \if ENABLE_EXAMPLES
2037 * \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
2038 * \ref py_mcumesh_buildPartOfMySelf "Here is a Python example".
2041 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2043 if(getMeshDimension()!=-1)
2044 return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
2048 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2050 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2052 return const_cast<MEDCouplingUMesh *>(this);
2057 * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2059 * This method allows to partially modify some cells in \b this (whose list is specified by [ \b cellIdsBg, \b cellIdsEnd ) ) with cells coming in \b otherOnSameCoordsThanThis.
2060 * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2061 * The number of cells of \b this will remain the same with this method.
2063 * \param [in] begin begin of cell ids (included) of cells in this to assign
2064 * \param [in] end end of cell ids (excluded) of cells in this to assign
2065 * \param [in] otherOnSameCoordsThanThis an another mesh with same meshdimension than \b this with exactly the same number of cells than cell ids list in [\b cellIdsBg, \b cellIdsEnd ).
2066 * Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2068 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2070 checkConnectivityFullyDefined();
2071 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2072 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2073 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2074 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2076 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2077 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2078 throw INTERP_KERNEL::Exception(oss.str().c_str());
2080 int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2081 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2083 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2084 throw INTERP_KERNEL::Exception(oss.str().c_str());
2086 int nbOfCells=getNumberOfCells();
2087 bool easyAssign=true;
2088 const int *connI=_nodal_connec_index->getConstPointer();
2089 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2090 for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2092 if(*it>=0 && *it<nbOfCells)
2094 easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2098 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2099 throw INTERP_KERNEL::Exception(oss.str().c_str());
2104 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2109 DataArrayInt *arrOut=0,*arrIOut=0;
2110 MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2112 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2113 setConnectivity(arrOut,arrIOut,true);
2117 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2119 checkConnectivityFullyDefined();
2120 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2121 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2122 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2123 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2125 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2126 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2127 throw INTERP_KERNEL::Exception(oss.str().c_str());
2129 int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2130 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2132 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2133 throw INTERP_KERNEL::Exception(oss.str().c_str());
2135 int nbOfCells=getNumberOfCells();
2136 bool easyAssign=true;
2137 const int *connI=_nodal_connec_index->getConstPointer();
2138 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2140 for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2142 if(it>=0 && it<nbOfCells)
2144 easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2148 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2149 throw INTERP_KERNEL::Exception(oss.str().c_str());
2154 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2159 DataArrayInt *arrOut=0,*arrIOut=0;
2160 MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2162 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2163 setConnectivity(arrOut,arrIOut,true);
2168 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2169 * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2170 * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2171 * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2173 * \param [in] begin input start of array of node ids.
2174 * \param [in] end input end of array of node ids.
2175 * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2176 * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2178 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2180 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2181 checkConnectivityFullyDefined();
2183 int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2184 std::vector<bool> fastFinder(sz,false);
2185 for(const int *work=begin;work!=end;work++)
2186 if(*work>=0 && *work<sz)
2187 fastFinder[*work]=true;
2188 int nbOfCells=getNumberOfCells();
2189 const int *conn=getNodalConnectivity()->getConstPointer();
2190 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2191 for(int i=0;i<nbOfCells;i++)
2193 int ref=0,nbOfHit=0;
2194 for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2198 if(fastFinder[*work2])
2201 if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2202 cellIdsKept->pushBackSilent(i);
2204 cellIdsKeptArr=cellIdsKept.retn();
2208 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2209 * this->getMeshDimension(), that bound some cells of \a this mesh.
2210 * The cells of lower dimension to include to the result mesh are selected basing on
2211 * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2212 * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2213 * ==\c false, a cell is copied if any its node is in the array of node ids. The
2214 * created mesh shares the node coordinates array with \a this mesh.
2215 * \param [in] begin - the array of node ids.
2216 * \param [in] end - a pointer to the (last+1)-th element of \a begin.
2217 * \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2218 * array \a begin are added, else cells whose any node is in the
2219 * array \a begin are added.
2220 * \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2221 * to delete this mesh using decrRef() as it is no more needed.
2222 * \throw If the coordinates array is not set.
2223 * \throw If the nodal connectivity of cells is not defined.
2224 * \throw If any node id in \a begin is not valid.
2226 * \if ENABLE_EXAMPLES
2227 * \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2228 * \ref py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2231 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2233 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2234 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2235 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2236 desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2237 return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2241 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2242 * this->getMeshDimension(), which bound only one cell of \a this mesh.
2243 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2244 * array of \a this mesh, else "free" nodes are removed from the result mesh
2245 * by calling zipCoords().
2246 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2247 * to delete this mesh using decrRef() as it is no more needed.
2248 * \throw If the coordinates array is not set.
2249 * \throw If the nodal connectivity of cells is not defined.
2251 * \if ENABLE_EXAMPLES
2252 * \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2253 * \ref py_mcumesh_buildBoundaryMesh "Here is a Python example".
2256 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2258 DataArrayInt *desc=DataArrayInt::New();
2259 DataArrayInt *descIndx=DataArrayInt::New();
2260 DataArrayInt *revDesc=DataArrayInt::New();
2261 DataArrayInt *revDescIndx=DataArrayInt::New();
2263 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2266 descIndx->decrRef();
2267 int nbOfCells=meshDM1->getNumberOfCells();
2268 const int *revDescIndxC=revDescIndx->getConstPointer();
2269 std::vector<int> boundaryCells;
2270 for(int i=0;i<nbOfCells;i++)
2271 if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2272 boundaryCells.push_back(i);
2273 revDescIndx->decrRef();
2274 MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2279 * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2280 * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2281 * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown.
2283 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2285 checkFullyDefined();
2286 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2287 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2288 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2289 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2291 buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2292 desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2294 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2295 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2296 const int *revDescPtr=revDesc->getConstPointer();
2297 const int *revDescIndxPtr=revDescIndx->getConstPointer();
2298 int nbOfCells=getNumberOfCells();
2299 std::vector<bool> ret1(nbOfCells,false);
2301 for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2302 if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2303 { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2305 DataArrayInt *ret2=DataArrayInt::New();
2307 int *ret2Ptr=ret2->getPointer();
2309 for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2312 ret2->setName("BoundaryCells");
2317 * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2318 * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2319 * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2320 * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2322 * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2323 * This method method returns cells ids set s = s1 + s2 where :
2325 * - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2326 * - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2328 * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2329 * are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2331 * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2332 * \param [out] cellIdsRk1 a newly allocated array containing cells ids of s1+s2 \b into \b cellIdsRk0 subset. To get absolute ids of s1+s2 simply invoke
2333 * cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2335 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2337 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2338 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2339 checkConnectivityFullyDefined();
2340 otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2341 if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2342 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2343 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2344 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2345 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2346 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2347 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2348 const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2349 DataArrayInt *idsOtherInConsti=0;
2350 bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2351 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2353 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2355 for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2356 s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2357 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2358 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2359 DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2360 ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2361 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2362 ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2363 neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2364 RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2365 neighThisPartAuto=0;
2366 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2367 const int li[2]={0,1};
2368 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2369 s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2370 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2373 cellIdsRk0=s0arr.retn();
2374 cellIdsRk1=s_renum1.retn();
2378 * This method computes the skin of \b this. That is to say the consituting meshdim-1 mesh is built and only the boundary subpart is
2379 * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2381 * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2383 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2385 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2386 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2387 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2388 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2390 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2391 revDesc=0; desc=0; descIndx=0;
2392 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2393 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2394 return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2398 * Finds nodes lying on the boundary of \a this mesh.
2399 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2400 * nodes. The caller is to delete this array using decrRef() as it is no
2402 * \throw If the coordinates array is not set.
2403 * \throw If the nodal connectivity of cells is node defined.
2405 * \if ENABLE_EXAMPLES
2406 * \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2407 * \ref py_mcumesh_findBoundaryNodes "Here is a Python example".
2410 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2412 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2413 return skin->computeFetchedNodeIds();
2416 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2419 return const_cast<MEDCouplingUMesh *>(this);
2423 * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2424 * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2425 * This method searches for nodes needed to be duplicated. These nodes are nodes fetched by \b otherDimM1OnSameCoords which are not part of the boundary of \b otherDimM1OnSameCoords.
2426 * If a node is in the boundary of \b this \b and in the boundary of \b otherDimM1OnSameCoords this node is considerd as needed to be duplicated.
2427 * When the set of node ids \b nodeIdsToDuplicate is computed, cell ids in \b this is searched so that their connectivity includes at least 1 node in \b nodeIdsToDuplicate.
2429 * \param [in] otherDimM1OnSameCoords a mesh lying on the same coords than \b this and with a mesh dimension equal to those of \b this minus 1. WARNING this input
2430 * parameter is altered during the call.
2431 * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2432 * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2433 * \param [out] cellIdsNotModified cell ids int \b this that lies on \b otherDimM1OnSameCoords mesh whose connectivity do \b not need to be modified as it is the case for \b cellIdsNeededToBeRenum.
2435 * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2437 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2438 DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const
2440 checkFullyDefined();
2441 otherDimM1OnSameCoords.checkFullyDefined();
2442 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2443 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2444 if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2445 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2446 DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2447 findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2448 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2449 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2450 s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2451 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2452 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2453 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2454 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2455 cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2457 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2458 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2459 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2460 DataArrayInt *idsTmp=0;
2461 bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2462 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2464 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2465 MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2466 DataArrayInt *tmp0=0,*tmp1=0;
2467 ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2468 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2469 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2470 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2471 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2472 cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2473 cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2475 cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2476 cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2477 nodeIdsToDuplicate=s3.retn();
2481 * This method operates a modification of the connectivity and coords in \b this.
2482 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2483 * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2484 * More explicitely the renumber array in nodes is not explicitely given in old2new to avoid to build a big array of renumbering whereas typically few node ids needs to be
2485 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2486 * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2488 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2490 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2491 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2493 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2495 int nbOfNodes=getNumberOfNodes();
2496 duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2497 duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2501 * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of
2502 * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range !
2504 * \param [in] offset - specifies the offset to be applied on each element of connectivity.
2506 * \sa renumberNodesInConn
2508 void MEDCouplingUMesh::renumberNodesWithOffsetInConn(int offset)
2510 checkConnectivityFullyDefined();
2511 int *conn(getNodalConnectivity()->getPointer());
2512 const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2513 int nbOfCells(getNumberOfCells());
2514 for(int i=0;i<nbOfCells;i++)
2515 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2517 int& node=conn[iconn];
2518 if(node>=0)//avoid polyhedron separator
2523 _nodal_connec->declareAsNew();
2528 * Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
2529 * of array. This method is dedicated for renumbering from a big set of nodes the a tiny set of nodes which is the case during extraction
2532 void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& newNodeNumbersO2N)
2534 checkConnectivityFullyDefined();
2535 int *conn(getNodalConnectivity()->getPointer());
2536 const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2537 int nbOfCells(getNumberOfCells());
2538 for(int i=0;i<nbOfCells;i++)
2539 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2541 int& node=conn[iconn];
2542 if(node>=0)//avoid polyhedron separator
2544 INTERP_KERNEL::HashMap<int,int>::const_iterator it(newNodeNumbersO2N.find(node));
2545 if(it!=newNodeNumbersO2N.end())
2551 std::ostringstream oss; oss << "MEDCouplingUMesh::renumberNodesInConn(map) : presence in connectivity for cell #" << i << " of node #" << node << " : Not in map !";
2552 throw INTERP_KERNEL::Exception(oss.str().c_str());
2556 _nodal_connec->declareAsNew();
2561 * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2562 * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2563 * This method is a generalization of shiftNodeNumbersInConn().
2564 * \warning This method performs no check of validity of new ids. **Use it with care !**
2565 * \param [in] newNodeNumbersO2N - a permutation array, of length \a
2566 * this->getNumberOfNodes(), in "Old to New" mode.
2567 * See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2568 * \throw If the nodal connectivity of cells is not defined.
2570 * \if ENABLE_EXAMPLES
2571 * \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2572 * \ref py_mcumesh_renumberNodesInConn "Here is a Python example".
2575 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2577 checkConnectivityFullyDefined();
2578 int *conn=getNodalConnectivity()->getPointer();
2579 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2580 int nbOfCells(getNumberOfCells());
2581 for(int i=0;i<nbOfCells;i++)
2582 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2584 int& node=conn[iconn];
2585 if(node>=0)//avoid polyhedron separator
2587 node=newNodeNumbersO2N[node];
2590 _nodal_connec->declareAsNew();
2595 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2596 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2597 * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2599 * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2601 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2603 checkConnectivityFullyDefined();
2604 int *conn=getNodalConnectivity()->getPointer();
2605 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2606 int nbOfCells=getNumberOfCells();
2607 for(int i=0;i<nbOfCells;i++)
2608 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2610 int& node=conn[iconn];
2611 if(node>=0)//avoid polyhedron separator
2616 _nodal_connec->declareAsNew();
2621 * This method operates a modification of the connectivity in \b this.
2622 * Coordinates are \b NOT considered here and will remain unchanged by this method. this->_coords can ever been null for the needs of this method.
2623 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2624 * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2625 * More explicitely the renumber array in nodes is not explicitely given in old2new to avoid to build a big array of renumbering whereas typically few node ids needs to be
2626 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2627 * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2629 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2630 * As an another consequense after the call of this method \b this can be transiently non cohrent.
2632 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2633 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2634 * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ).
2636 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2638 checkConnectivityFullyDefined();
2639 std::map<int,int> m;
2641 for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2643 int *conn=getNodalConnectivity()->getPointer();
2644 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2645 int nbOfCells=getNumberOfCells();
2646 for(int i=0;i<nbOfCells;i++)
2647 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2649 int& node=conn[iconn];
2650 if(node>=0)//avoid polyhedron separator
2652 std::map<int,int>::iterator it=m.find(node);
2661 * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2663 * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2664 * After the call of this method the number of cells remains the same as before.
2666 * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2667 * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2668 * be strictly in [0;this->getNumberOfCells()).
2670 * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2671 * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2672 * should be contained in[0;this->getNumberOfCells()).
2674 * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2676 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2678 checkConnectivityFullyDefined();
2679 int nbCells=getNumberOfCells();
2680 const int *array=old2NewBg;
2682 array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2684 const int *conn=_nodal_connec->getConstPointer();
2685 const int *connI=_nodal_connec_index->getConstPointer();
2686 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2687 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2688 const int *n2oPtr=n2o->begin();
2689 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2690 newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2691 newConn->copyStringInfoFrom(*_nodal_connec);
2692 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2693 newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2694 newConnI->copyStringInfoFrom(*_nodal_connec_index);
2696 int *newC=newConn->getPointer();
2697 int *newCI=newConnI->getPointer();
2700 for(int i=0;i<nbCells;i++)
2703 int nbOfElts=connI[pos+1]-connI[pos];
2704 newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2709 setConnectivity(newConn,newConnI);
2711 free(const_cast<int *>(array));
2715 * Finds cells whose bounding boxes intersect a given bounding box.
2716 * \param [in] bbox - an array defining the bounding box via coordinates of its
2717 * extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2719 * \param [in] eps - a factor used to increase size of the bounding box of cell
2720 * before comparing it with \a bbox. This factor is multiplied by the maximal
2721 * extent of the bounding box of cell to produce an addition to this bounding box.
2722 * \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2723 * cells. The caller is to delete this array using decrRef() as it is no more
2725 * \throw If the coordinates array is not set.
2726 * \throw If the nodal connectivity of cells is not defined.
2728 * \if ENABLE_EXAMPLES
2729 * \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2730 * \ref py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2733 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2735 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2736 if(getMeshDimension()==-1)
2738 elems->pushBackSilent(0);
2739 return elems.retn();
2741 int dim=getSpaceDimension();
2742 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2743 const int* conn = getNodalConnectivity()->getConstPointer();
2744 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2745 const double* coords = getCoords()->getConstPointer();
2746 int nbOfCells=getNumberOfCells();
2747 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2749 for (int i=0; i<dim; i++)
2751 elem_bb[i*2]=std::numeric_limits<double>::max();
2752 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2755 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2757 int node= conn[inode];
2758 if(node>=0)//avoid polyhedron separator
2760 for (int idim=0; idim<dim; idim++)
2762 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2764 elem_bb[idim*2] = coords[node*dim+idim] ;
2766 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2768 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2773 if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2774 elems->pushBackSilent(ielem);
2776 return elems.retn();
2780 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2781 * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2782 * added in 'elems' parameter.
2784 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2786 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2787 if(getMeshDimension()==-1)
2789 elems->pushBackSilent(0);
2790 return elems.retn();
2792 int dim=getSpaceDimension();
2793 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2794 const int* conn = getNodalConnectivity()->getConstPointer();
2795 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2796 const double* coords = getCoords()->getConstPointer();
2797 int nbOfCells=getNumberOfCells();
2798 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2800 for (int i=0; i<dim; i++)
2802 elem_bb[i*2]=std::numeric_limits<double>::max();
2803 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2806 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2808 int node= conn[inode];
2809 if(node>=0)//avoid polyhedron separator
2811 for (int idim=0; idim<dim; idim++)
2813 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2815 elem_bb[idim*2] = coords[node*dim+idim] ;
2817 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2819 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2824 if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2825 elems->pushBackSilent(ielem);
2827 return elems.retn();
2831 * Returns a type of a cell by its id.
2832 * \param [in] cellId - the id of the cell of interest.
2833 * \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2834 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2836 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2838 const int *ptI=_nodal_connec_index->getConstPointer();
2839 const int *pt=_nodal_connec->getConstPointer();
2840 if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2841 return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2844 std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2845 throw INTERP_KERNEL::Exception(oss.str().c_str());
2850 * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2851 * This method does not throw exception if geometric type \a type is not in \a this.
2852 * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2853 * The coordinates array is not considered here.
2855 * \param [in] type the geometric type
2856 * \return cell ids in this having geometric type \a type.
2858 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2861 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2863 checkConnectivityFullyDefined();
2864 int nbCells=getNumberOfCells();
2865 int mdim=getMeshDimension();
2866 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2867 if(mdim!=(int)cm.getDimension())
2868 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2869 const int *ptI=_nodal_connec_index->getConstPointer();
2870 const int *pt=_nodal_connec->getConstPointer();
2871 for(int i=0;i<nbCells;i++)
2873 if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2874 ret->pushBackSilent(i);
2880 * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2882 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2884 const int *ptI=_nodal_connec_index->getConstPointer();
2885 const int *pt=_nodal_connec->getConstPointer();
2886 int nbOfCells=getNumberOfCells();
2888 for(int i=0;i<nbOfCells;i++)
2889 if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2895 * Returns the nodal connectivity of a given cell.
2896 * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2897 * all returned node ids can be used in getCoordinatesOfNode().
2898 * \param [in] cellId - an id of the cell of interest.
2899 * \param [in,out] conn - a vector where the node ids are appended. It is not
2900 * cleared before the appending.
2901 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2903 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2905 const int *ptI=_nodal_connec_index->getConstPointer();
2906 const int *pt=_nodal_connec->getConstPointer();
2907 for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2912 std::string MEDCouplingUMesh::simpleRepr() const
2914 static const char msg0[]="No coordinates specified !";
2915 std::ostringstream ret;
2916 ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2917 ret << "Description of mesh : \"" << getDescription() << "\"\n";
2919 double tt=getTime(tmpp1,tmpp2);
2920 ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2921 ret << "Iteration : " << tmpp1 << " Order : " << tmpp2 << "\n";
2923 { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2925 { ret << " Mesh dimension has not been set or is invalid !"; }
2928 const int spaceDim=getSpaceDimension();
2929 ret << spaceDim << "\nInfo attached on space dimension : ";
2930 for(int i=0;i<spaceDim;i++)
2931 ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2935 ret << msg0 << "\n";
2936 ret << "Number of nodes : ";
2938 ret << getNumberOfNodes() << "\n";
2940 ret << msg0 << "\n";
2941 ret << "Number of cells : ";
2942 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2943 ret << getNumberOfCells() << "\n";
2945 ret << "No connectivity specified !" << "\n";
2946 ret << "Cell types present : ";
2947 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2949 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2950 ret << cm.getRepr() << " ";
2956 std::string MEDCouplingUMesh::advancedRepr() const
2958 std::ostringstream ret;
2959 ret << simpleRepr();
2960 ret << "\nCoordinates array : \n___________________\n\n";
2962 _coords->reprWithoutNameStream(ret);
2964 ret << "No array set !\n";
2965 ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2966 reprConnectivityOfThisLL(ret);
2971 * This method returns a C++ code that is a dump of \a this.
2972 * This method will throw if this is not fully defined.
2974 std::string MEDCouplingUMesh::cppRepr() const
2976 static const char coordsName[]="coords";
2977 static const char connName[]="conn";
2978 static const char connIName[]="connI";
2979 checkFullyDefined();
2980 std::ostringstream ret; ret << "// coordinates" << std::endl;
2981 _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2982 _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2983 _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2984 ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2985 ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2986 ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2987 ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2991 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2993 std::ostringstream ret;
2994 reprConnectivityOfThisLL(ret);
2999 * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
3000 * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
3001 * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
3004 * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
3005 * This method analyzes the 3 arrays of \a this. For each the following behaviour is done : if the array is null a newly one is created
3006 * with number of tuples set to 0, if not the array is taken as this in the returned instance.
3008 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
3010 int mdim=getMeshDimension();
3012 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
3013 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
3014 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
3015 bool needToCpyCT=true;
3018 tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
3026 if(!_nodal_connec_index)
3028 tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
3033 tmp2=_nodal_connec_index;
3036 ret->setConnectivity(tmp1,tmp2,false);
3041 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
3042 ret->setCoords(coords);
3045 ret->setCoords(_coords);
3049 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
3051 if(_nodal_connec!=0 && _nodal_connec_index!=0)
3053 int nbOfCells=getNumberOfCells();
3054 const int *c=_nodal_connec->getConstPointer();
3055 const int *ci=_nodal_connec_index->getConstPointer();
3056 for(int i=0;i<nbOfCells;i++)
3058 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3059 stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3060 std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3065 stream << "Connectivity not defined !\n";
3068 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3070 const int *ptI=_nodal_connec_index->getConstPointer();
3071 const int *pt=_nodal_connec->getConstPointer();
3072 if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3073 return ptI[cellId+1]-ptI[cellId]-1;
3075 return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3079 * Returns types of cells of the specified part of \a this mesh.
3080 * This method avoids computing sub-mesh explicitely to get its types.
3081 * \param [in] begin - an array of cell ids of interest.
3082 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3083 * \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3084 * describing the cell types.
3085 * \throw If the coordinates array is not set.
3086 * \throw If the nodal connectivity of cells is not defined.
3087 * \sa getAllGeoTypes()
3089 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3091 checkFullyDefined();
3092 std::set<INTERP_KERNEL::NormalizedCellType> ret;
3093 const int *conn=_nodal_connec->getConstPointer();
3094 const int *connIndex=_nodal_connec_index->getConstPointer();
3095 for(const int *w=begin;w!=end;w++)
3096 ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3101 * Defines the nodal connectivity using given connectivity arrays. Optionally updates
3102 * a set of types of cells constituting \a this mesh.
3103 * This method is for advanced users having prepared their connectivity before. For
3104 * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3105 * \param [in] conn - the nodal connectivity array.
3106 * \param [in] connIndex - the nodal connectivity index array.
3107 * \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3110 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3112 DataArrayInt::SetArrayIn(conn,_nodal_connec);
3113 DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3114 if(isComputingTypes)
3120 * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
3121 * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3123 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3124 _nodal_connec(0),_nodal_connec_index(0),
3125 _types(other._types)
3127 if(other._nodal_connec)
3128 _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3129 if(other._nodal_connec_index)
3130 _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3133 MEDCouplingUMesh::~MEDCouplingUMesh()
3136 _nodal_connec->decrRef();
3137 if(_nodal_connec_index)
3138 _nodal_connec_index->decrRef();
3142 * Recomputes a set of cell types of \a this mesh. For more info see
3143 * \ref MEDCouplingUMeshNodalConnectivity.
3145 void MEDCouplingUMesh::computeTypes()
3147 if(_nodal_connec && _nodal_connec_index)
3150 const int *conn=_nodal_connec->getConstPointer();
3151 const int *connIndex=_nodal_connec_index->getConstPointer();
3152 int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
3154 for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
3155 _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
3160 * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3162 void MEDCouplingUMesh::checkFullyDefined() const
3164 if(!_nodal_connec_index || !_nodal_connec || !_coords)
3165 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3169 * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3171 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3173 if(!_nodal_connec_index || !_nodal_connec)
3174 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3178 * Returns a number of cells constituting \a this mesh.
3179 * \return int - the number of cells in \a this mesh.
3180 * \throw If the nodal connectivity of cells is not defined.
3182 int MEDCouplingUMesh::getNumberOfCells() const
3184 if(_nodal_connec_index)
3185 return _nodal_connec_index->getNumberOfTuples()-1;
3190 throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3194 * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3195 * mesh. For more info see \ref MEDCouplingMeshesPage.
3196 * \return int - the dimension of \a this mesh.
3197 * \throw If the mesh dimension is not defined using setMeshDimension().
3199 int MEDCouplingUMesh::getMeshDimension() const
3202 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3207 * Returns a length of the nodal connectivity array.
3208 * This method is for test reason. Normally the integer returned is not useable by
3209 * user. For more info see \ref MEDCouplingUMeshNodalConnectivity.
3210 * \return int - the length of the nodal connectivity array.
3212 int MEDCouplingUMesh::getMeshLength() const
3214 return _nodal_connec->getNbOfElems();
3218 * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3220 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3222 MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3223 tinyInfo.push_back(getMeshDimension());
3224 tinyInfo.push_back(getNumberOfCells());
3226 tinyInfo.push_back(getMeshLength());
3228 tinyInfo.push_back(-1);
3232 * First step of unserialization process.
3234 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3236 return tinyInfo[6]<=0;
3240 * Second step of serialization process.
3241 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3243 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3245 MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3247 a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3251 * Third and final step of serialization process.
3253 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3255 MEDCouplingPointSet::serialize(a1,a2);
3256 if(getMeshDimension()>-1)
3258 a1=DataArrayInt::New();
3259 a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3260 int *ptA1=a1->getPointer();
3261 const int *conn=getNodalConnectivity()->getConstPointer();
3262 const int *index=getNodalConnectivityIndex()->getConstPointer();
3263 ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3264 std::copy(conn,conn+getMeshLength(),ptA1);
3271 * Second and final unserialization process.
3272 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3274 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3276 MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3277 setMeshDimension(tinyInfo[5]);
3281 const int *recvBuffer=a1->getConstPointer();
3282 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3283 myConnecIndex->alloc(tinyInfo[6]+1,1);
3284 std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3285 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3286 myConnec->alloc(tinyInfo[7],1);
3287 std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3288 setConnectivity(myConnec, myConnecIndex);
3293 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3294 * CellIds are given using range specified by a start an end and step.
3296 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3298 checkFullyDefined();
3299 int ncell=getNumberOfCells();
3300 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3301 ret->_mesh_dim=_mesh_dim;
3302 ret->setCoords(_coords);
3303 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3304 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3305 int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3307 const int *conn=_nodal_connec->getConstPointer();
3308 const int *connIndex=_nodal_connec_index->getConstPointer();
3309 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3311 if(work>=0 && work<ncell)
3313 newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3317 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3318 throw INTERP_KERNEL::Exception(oss.str().c_str());
3321 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3322 int *newConnPtr=newConn->getPointer();
3323 std::set<INTERP_KERNEL::NormalizedCellType> types;
3325 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3327 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3328 newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3330 ret->setConnectivity(newConn,newConnI,false);
3332 ret->copyTinyInfoFrom(this);
3337 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3338 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3339 * The return newly allocated mesh will share the same coordinates as \a this.
3341 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3343 checkConnectivityFullyDefined();
3344 int ncell=getNumberOfCells();
3345 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3346 ret->_mesh_dim=_mesh_dim;
3347 ret->setCoords(_coords);
3348 std::size_t nbOfElemsRet=std::distance(begin,end);
3349 int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3351 const int *conn=_nodal_connec->getConstPointer();
3352 const int *connIndex=_nodal_connec_index->getConstPointer();
3354 for(const int *work=begin;work!=end;work++,newNbring++)
3356 if(*work>=0 && *work<ncell)
3357 connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3361 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3362 throw INTERP_KERNEL::Exception(oss.str().c_str());
3365 int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3366 int *connRetWork=connRet;
3367 std::set<INTERP_KERNEL::NormalizedCellType> types;
3368 for(const int *work=begin;work!=end;work++)
3370 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3371 connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3373 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3374 connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3375 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3376 connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3377 ret->setConnectivity(connRetArr,connIndexRetArr,false);
3379 ret->copyTinyInfoFrom(this);
3384 * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3386 * For 1D cells, the returned field contains lengths.<br>
3387 * For 2D cells, the returned field contains areas.<br>
3388 * For 3D cells, the returned field contains volumes.
3389 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3390 * orientation, i.e. the volume is always positive.
3391 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3392 * and one time . The caller is to delete this field using decrRef() as it is no
3395 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3397 std::string name="MeasureOfMesh_";
3399 int nbelem=getNumberOfCells();
3400 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3401 field->setName(name);
3402 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3403 array->alloc(nbelem,1);
3404 double *area_vol=array->getPointer();
3405 field->setArray(array) ; array=0;
3406 field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3407 field->synchronizeTimeWithMesh();
3408 if(getMeshDimension()!=-1)
3411 INTERP_KERNEL::NormalizedCellType type;
3412 int dim_space=getSpaceDimension();
3413 const double *coords=getCoords()->getConstPointer();
3414 const int *connec=getNodalConnectivity()->getConstPointer();
3415 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3416 for(int iel=0;iel<nbelem;iel++)
3418 ipt=connec_index[iel];
3419 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3420 area_vol[iel]=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[iel+1]-ipt-1,coords,dim_space);
3423 std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3427 area_vol[0]=std::numeric_limits<double>::max();
3429 return field.retn();
3433 * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3435 * For 1D cells, the returned array contains lengths.<br>
3436 * For 2D cells, the returned array contains areas.<br>
3437 * For 3D cells, the returned array contains volumes.
3438 * This method avoids building explicitly a part of \a this mesh to perform the work.
3439 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3440 * orientation, i.e. the volume is always positive.
3441 * \param [in] begin - an array of cell ids of interest.
3442 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3443 * \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3444 * delete this array using decrRef() as it is no more needed.
3446 * \if ENABLE_EXAMPLES
3447 * \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3448 * \ref py_mcumesh_getPartMeasureField "Here is a Python example".
3450 * \sa getMeasureField()
3452 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3454 std::string name="PartMeasureOfMesh_";
3456 int nbelem=(int)std::distance(begin,end);
3457 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3458 array->setName(name);
3459 array->alloc(nbelem,1);
3460 double *area_vol=array->getPointer();
3461 if(getMeshDimension()!=-1)
3464 INTERP_KERNEL::NormalizedCellType type;
3465 int dim_space=getSpaceDimension();
3466 const double *coords=getCoords()->getConstPointer();
3467 const int *connec=getNodalConnectivity()->getConstPointer();
3468 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3469 for(const int *iel=begin;iel!=end;iel++)
3471 ipt=connec_index[*iel];
3472 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3473 *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3476 std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3480 area_vol[0]=std::numeric_limits<double>::max();
3482 return array.retn();
3486 * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3487 * \a this one. The returned field contains the dual cell volume for each corresponding
3488 * node in \a this mesh. In other words, the field returns the getMeasureField() of
3489 * the dual mesh in P1 sens of \a this.<br>
3490 * For 1D cells, the returned field contains lengths.<br>
3491 * For 2D cells, the returned field contains areas.<br>
3492 * For 3D cells, the returned field contains volumes.
3493 * This method is useful to check "P1*" conservative interpolators.
3494 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3495 * orientation, i.e. the volume is always positive.
3496 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3497 * nodes and one time. The caller is to delete this array using decrRef() as
3498 * it is no more needed.
3500 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3502 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3503 std::string name="MeasureOnNodeOfMesh_";
3505 int nbNodes=getNumberOfNodes();
3506 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3507 double cst=1./((double)getMeshDimension()+1.);
3508 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3509 array->alloc(nbNodes,1);
3510 double *valsToFill=array->getPointer();
3511 std::fill(valsToFill,valsToFill+nbNodes,0.);
3512 const double *values=tmp->getArray()->getConstPointer();
3513 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3514 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3515 getReverseNodalConnectivity(da,daInd);
3516 const int *daPtr=da->getConstPointer();
3517 const int *daIPtr=daInd->getConstPointer();
3518 for(int i=0;i<nbNodes;i++)
3519 for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3520 valsToFill[i]+=cst*values[*cell];
3522 ret->setArray(array);
3527 * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3528 * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3529 * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3530 * and are normalized.
3531 * <br> \a this can be either
3532 * - a 2D mesh in 2D or 3D space or
3533 * - an 1D mesh in 2D space.
3535 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3536 * cells and one time. The caller is to delete this field using decrRef() as
3537 * it is no more needed.
3538 * \throw If the nodal connectivity of cells is not defined.
3539 * \throw If the coordinates array is not set.
3540 * \throw If the mesh dimension is not set.
3541 * \throw If the mesh and space dimension is not as specified above.
3543 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3545 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3546 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3547 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3548 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3549 int nbOfCells=getNumberOfCells();
3550 int nbComp=getMeshDimension()+1;
3551 array->alloc(nbOfCells,nbComp);
3552 double *vals=array->getPointer();
3553 const int *connI=_nodal_connec_index->getConstPointer();
3554 const int *conn=_nodal_connec->getConstPointer();
3555 const double *coords=_coords->getConstPointer();
3556 if(getMeshDimension()==2)
3558 if(getSpaceDimension()==3)
3560 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3561 const double *locPtr=loc->getConstPointer();
3562 for(int i=0;i<nbOfCells;i++,vals+=3)
3564 int offset=connI[i];
3565 INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3566 double n=INTERP_KERNEL::norm<3>(vals);
3567 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3572 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3573 const double *isAbsPtr=isAbs->getArray()->begin();
3574 for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3575 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3578 else//meshdimension==1
3581 for(int i=0;i<nbOfCells;i++)
3583 int offset=connI[i];
3584 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3585 double n=INTERP_KERNEL::norm<2>(tmp);
3586 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3591 ret->setArray(array);
3593 ret->synchronizeTimeWithSupport();
3598 * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3599 * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3600 * and are normalized.
3601 * <br> \a this can be either
3602 * - a 2D mesh in 2D or 3D space or
3603 * - an 1D mesh in 2D space.
3605 * This method avoids building explicitly a part of \a this mesh to perform the work.
3606 * \param [in] begin - an array of cell ids of interest.
3607 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3608 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3609 * cells and one time. The caller is to delete this field using decrRef() as
3610 * it is no more needed.
3611 * \throw If the nodal connectivity of cells is not defined.
3612 * \throw If the coordinates array is not set.
3613 * \throw If the mesh dimension is not set.
3614 * \throw If the mesh and space dimension is not as specified above.
3615 * \sa buildOrthogonalField()
3617 * \if ENABLE_EXAMPLES
3618 * \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3619 * \ref py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3622 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3624 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3625 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3626 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3627 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3628 std::size_t nbelems=std::distance(begin,end);
3629 int nbComp=getMeshDimension()+1;
3630 array->alloc((int)nbelems,nbComp);
3631 double *vals=array->getPointer();
3632 const int *connI=_nodal_connec_index->getConstPointer();
3633 const int *conn=_nodal_connec->getConstPointer();
3634 const double *coords=_coords->getConstPointer();
3635 if(getMeshDimension()==2)
3637 if(getSpaceDimension()==3)
3639 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3640 const double *locPtr=loc->getConstPointer();
3641 for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3643 int offset=connI[*i];
3644 INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3645 double n=INTERP_KERNEL::norm<3>(vals);
3646 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3651 for(std::size_t i=0;i<nbelems;i++)
3652 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3655 else//meshdimension==1
3658 for(const int *i=begin;i!=end;i++)
3660 int offset=connI[*i];
3661 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3662 double n=INTERP_KERNEL::norm<2>(tmp);
3663 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3668 ret->setArray(array);
3670 ret->synchronizeTimeWithSupport();
3675 * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3676 * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3677 * and are \b not normalized.
3678 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3679 * cells and one time. The caller is to delete this field using decrRef() as
3680 * it is no more needed.
3681 * \throw If the nodal connectivity of cells is not defined.
3682 * \throw If the coordinates array is not set.
3683 * \throw If \a this->getMeshDimension() != 1.
3684 * \throw If \a this mesh includes cells of type other than SEG2.
3686 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3688 if(getMeshDimension()!=1)
3689 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3690 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3691 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3692 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3693 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3694 int nbOfCells=getNumberOfCells();
3695 int spaceDim=getSpaceDimension();
3696 array->alloc(nbOfCells,spaceDim);
3697 double *pt=array->getPointer();
3698 const double *coo=getCoords()->getConstPointer();
3699 std::vector<int> conn;
3701 for(int i=0;i<nbOfCells;i++)
3704 getNodeIdsOfCell(i,conn);
3705 pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3707 ret->setArray(array);
3709 ret->synchronizeTimeWithSupport();
3714 * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3715 * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3716 * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3717 * from. If a result face is shared by two 3D cells, then the face in included twice in
3719 * \param [in] origin - 3 components of a point defining location of the plane.
3720 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3721 * must be greater than 1e-6.
3722 * \param [in] eps - half-thickness of the plane.
3723 * \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3724 * producing correspondent 2D cells. The caller is to delete this array
3725 * using decrRef() as it is no more needed.
3726 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3727 * not share the node coordinates array with \a this mesh. The caller is to
3728 * delete this mesh using decrRef() as it is no more needed.
3729 * \throw If the coordinates array is not set.
3730 * \throw If the nodal connectivity of cells is not defined.
3731 * \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3732 * \throw If magnitude of \a vec is less than 1e-6.
3733 * \throw If the plane does not intersect any 3D cell of \a this mesh.
3734 * \throw If \a this includes quadratic cells.
3736 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3738 checkFullyDefined();
3739 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3740 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3741 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3742 if(candidates->empty())
3743 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3744 std::vector<int> nodes;
3745 DataArrayInt *cellIds1D=0;
3746 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3747 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3748 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3749 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3750 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3751 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3752 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3753 revDesc2=0; revDescIndx2=0;
3754 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3755 revDesc1=0; revDescIndx1=0;
3756 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3757 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3759 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3760 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3762 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3763 std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3764 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3765 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3766 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3767 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3768 connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3769 subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3770 if(cellIds2->empty())
3771 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3772 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3773 ret->setCoords(mDesc1->getCoords());
3774 ret->setConnectivity(conn,connI,true);
3775 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3780 * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3781 addition to the mesh, returns a new DataArrayInt, of length equal to the number of 1D cells in the result mesh, holding, for each cell in the result mesh, an id of a 2D cell it comes
3782 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3784 * \param [in] origin - 3 components of a point defining location of the plane.
3785 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3786 * must be greater than 1e-6.
3787 * \param [in] eps - half-thickness of the plane.
3788 * \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3789 * producing correspondent segments. The caller is to delete this array
3790 * using decrRef() as it is no more needed.
3791 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3792 * mesh in 3D space. This mesh does not share the node coordinates array with
3793 * \a this mesh. The caller is to delete this mesh using decrRef() as it is
3795 * \throw If the coordinates array is not set.
3796 * \throw If the nodal connectivity of cells is not defined.
3797 * \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3798 * \throw If magnitude of \a vec is less than 1e-6.
3799 * \throw If the plane does not intersect any 2D cell of \a this mesh.
3800 * \throw If \a this includes quadratic cells.
3802 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3804 checkFullyDefined();
3805 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3806 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3807 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3808 if(candidates->empty())
3809 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3810 std::vector<int> nodes;
3811 DataArrayInt *cellIds1D=0;
3812 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3813 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3814 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3815 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3816 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3817 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3818 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3819 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3820 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3822 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3823 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3825 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3826 int ncellsSub=subMesh->getNumberOfCells();
3827 std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3828 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3829 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3830 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3831 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3833 const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3834 const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3835 for(int i=0;i<ncellsSub;i++)
3837 if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3839 if(cut3DSurf[i].first!=-2)
3841 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3842 connI->pushBackSilent(conn->getNumberOfTuples());
3843 cellIds2->pushBackSilent(i);
3847 int cellId3DSurf=cut3DSurf[i].second;
3848 int offset=nodalI[cellId3DSurf]+1;
3849 int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3850 for(int j=0;j<nbOfEdges;j++)
3852 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3853 connI->pushBackSilent(conn->getNumberOfTuples());
3854 cellIds2->pushBackSilent(cellId3DSurf);
3859 if(cellIds2->empty())
3860 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3861 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3862 ret->setCoords(mDesc1->getCoords());
3863 ret->setConnectivity(conn,connI,true);
3864 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3869 * Finds cells whose bounding boxes intersect a given plane.
3870 * \param [in] origin - 3 components of a point defining location of the plane.
3871 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3872 * must be greater than 1e-6.
3873 * \param [in] eps - half-thickness of the plane.
3874 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3875 * cells. The caller is to delete this array using decrRef() as it is no more
3877 * \throw If the coordinates array is not set.
3878 * \throw If the nodal connectivity of cells is not defined.
3879 * \throw If \a this->getSpaceDimension() != 3.
3880 * \throw If magnitude of \a vec is less than 1e-6.
3881 * \sa buildSlice3D()
3883 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3885 checkFullyDefined();
3886 if(getSpaceDimension()!=3)
3887 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3888 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3890 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3892 vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3893 double angle=acos(vec[2]/normm);
3894 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3898 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3899 double normm2(sqrt(vec2[0]*vec2[0]+vec2[1]*vec2[1]+vec2[2]*vec2[2]));
3900 if(normm2/normm>1e-6)
3901 MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3902 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3904 mw->getBoundingBox(bbox);
3905 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3906 cellIds=mw->getCellsInBoundingBox(bbox,eps);
3910 getBoundingBox(bbox);
3911 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3912 cellIds=getCellsInBoundingBox(bbox,eps);
3914 return cellIds.retn();
3918 * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3919 * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3920 * No consideration of coordinate is done by this method.
3921 * 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)
3922 * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3924 bool MEDCouplingUMesh::isContiguous1D() const
3926 if(getMeshDimension()!=1)
3927 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3928 int nbCells=getNumberOfCells();
3930 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3931 const int *connI=_nodal_connec_index->getConstPointer();
3932 const int *conn=_nodal_connec->getConstPointer();
3933 int ref=conn[connI[0]+2];
3934 for(int i=1;i<nbCells;i++)
3936 if(conn[connI[i]+1]!=ref)
3938 ref=conn[connI[i]+2];
3944 * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3945 * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3946 * \param pt reference point of the line
3947 * \param v normalized director vector of the line
3948 * \param eps max precision before throwing an exception
3949 * \param res output of size this->getNumberOfCells
3951 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3953 if(getMeshDimension()!=1)
3954 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3955 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3956 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3957 if(getSpaceDimension()!=3)
3958 throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3959 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3960 const double *fPtr=f->getArray()->getConstPointer();
3962 for(int i=0;i<getNumberOfCells();i++)
3964 const double *tmp1=fPtr+3*i;
3965 tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3966 tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3967 tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3968 double n1=INTERP_KERNEL::norm<3>(tmp);
3969 n1/=INTERP_KERNEL::norm<3>(tmp1);
3971 throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3973 const double *coo=getCoords()->getConstPointer();
3974 for(int i=0;i<getNumberOfNodes();i++)
3976 std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3977 std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3978 res[i]=std::accumulate(tmp,tmp+3,0.);
3983 * 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.
3984 * \a this is expected to be a mesh so that its space dimension is equal to its
3985 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3986 * 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).
3988 * 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
3989 * 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).
3990 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3992 * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3993 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3995 * \param [in] ptBg the start pointer (included) of the coordinates of the point
3996 * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3997 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3998 * \return the positive value of the distance.
3999 * \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
4001 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
4003 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
4005 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4006 if(meshDim!=spaceDim-1)
4007 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
4008 if(meshDim!=2 && meshDim!=1)
4009 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4010 checkFullyDefined();
4011 if((int)std::distance(ptBg,ptEnd)!=spaceDim)
4012 { 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()); }
4013 DataArrayInt *ret1=0;
4014 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
4015 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
4016 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
4017 cellId=*ret1Safe->begin();
4018 return *ret0->begin();
4022 * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
4023 * to \a this and the first \a cellId in \a this corresponding to the returned distance.
4024 * 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
4025 * 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).
4026 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4028 * \a this is expected to be a mesh so that its space dimension is equal to its
4029 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4030 * 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).
4032 * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
4033 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4035 * \param [in] pts the list of points in which each tuple represents a point
4036 * \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.
4037 * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
4038 * \throw if number of components of \a pts is not equal to the space dimension.
4039 * \throw if mesh dimension of \a this is not equal to space dimension - 1.
4040 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
4042 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
4045 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
4046 pts->checkAllocated();
4047 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4048 if(meshDim!=spaceDim-1)
4049 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
4050 if(meshDim!=2 && meshDim!=1)
4051 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
4052 if(pts->getNumberOfComponents()!=spaceDim)
4054 std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
4055 throw INTERP_KERNEL::Exception(oss.str().c_str());
4057 checkFullyDefined();
4058 int nbCells=getNumberOfCells();
4060 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4061 int nbOfPts=pts->getNumberOfTuples();
4062 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4063 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4064 const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4065 double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4066 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4067 const double *bbox(bboxArr->begin());
4072 BBTreeDst<3> myTree(bbox,0,0,nbCells);
4073 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4075 double x=std::numeric_limits<double>::max();
4076 std::vector<int> elems;
4077 myTree.getMinDistanceOfMax(ptsPtr,x);
4078 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4079 DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4085 BBTreeDst<2> myTree(bbox,0,0,nbCells);
4086 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4088 double x=std::numeric_limits<double>::max();
4089 std::vector<int> elems;
4090 myTree.getMinDistanceOfMax(ptsPtr,x);
4091 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4092 DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4097 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4099 cellIds=ret1.retn();
4104 * \param [in] pt the start pointer (included) of the coordinates of the point
4105 * \param [in] cellIdsBg the start pointer (included) of cellIds
4106 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4107 * \param [in] nc nodal connectivity
4108 * \param [in] ncI nodal connectivity index
4109 * \param [in,out] ret0 the min distance between \a this and the external input point
4110 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4111 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4113 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)
4116 ret0=std::numeric_limits<double>::max();
4117 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4119 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4121 case INTERP_KERNEL::NORM_TRI3:
4123 double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4125 { ret0=tmp; cellId=*zeCell; }
4128 case INTERP_KERNEL::NORM_QUAD4:
4129 case INTERP_KERNEL::NORM_POLYGON:
4131 double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4133 { ret0=tmp; cellId=*zeCell; }
4137 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4143 * \param [in] pt the start pointer (included) of the coordinates of the point
4144 * \param [in] cellIdsBg the start pointer (included) of cellIds
4145 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4146 * \param [in] nc nodal connectivity
4147 * \param [in] ncI nodal connectivity index
4148 * \param [in,out] ret0 the min distance between \a this and the external input point
4149 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4150 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4152 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)
4155 ret0=std::numeric_limits<double>::max();
4156 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4158 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4160 case INTERP_KERNEL::NORM_SEG2:
4162 std::size_t uselessEntry=0;
4163 double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4166 { ret0=tmp; cellId=*zeCell; }
4170 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4176 * Finds cells in contact with a ball (i.e. a point with precision).
4177 * 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.
4178 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4180 * \warning This method is suitable if the caller intends to evaluate only one
4181 * point, for more points getCellsContainingPoints() is recommended as it is
4183 * \param [in] pos - array of coordinates of the ball central point.
4184 * \param [in] eps - ball radius.
4185 * \return int - a smallest id of cells being in contact with the ball, -1 in case
4186 * if there are no such cells.
4187 * \throw If the coordinates array is not set.
4188 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4190 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4192 std::vector<int> elts;
4193 getCellsContainingPoint(pos,eps,elts);
4196 return elts.front();
4200 * Finds cells in contact with a ball (i.e. a point with precision).
4201 * 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.
4202 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4203 * \warning This method is suitable if the caller intends to evaluate only one
4204 * point, for more points getCellsContainingPoints() is recommended as it is
4206 * \param [in] pos - array of coordinates of the ball central point.
4207 * \param [in] eps - ball radius.
4208 * \param [out] elts - vector returning ids of the found cells. It is cleared
4209 * before inserting ids.
4210 * \throw If the coordinates array is not set.
4211 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4213 * \if ENABLE_EXAMPLES
4214 * \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4215 * \ref py_mcumesh_getCellsContainingPoint "Here is a Python example".
4218 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4220 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4221 getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4222 elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4227 namespace ParaMEDMEM
4229 template<const int SPACEDIMM>
4233 static const int MY_SPACEDIM=SPACEDIMM;
4234 static const int MY_MESHDIM=8;
4235 typedef int MyConnType;
4236 static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4238 // useless, but for windows compilation ...
4239 const double* getCoordinatesPtr() const { return 0; }
4240 const int* getConnectivityPtr() const { return 0; }
4241 const int* getConnectivityIndexPtr() const { return 0; }
4242 INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4246 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m)
4248 INTERP_KERNEL::Edge *ret(0);
4249 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]));
4250 m[n0]=bg[0]; m[n1]=bg[1];
4253 case INTERP_KERNEL::NORM_SEG2:
4255 ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4258 case INTERP_KERNEL::NORM_SEG3:
4260 INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4261 INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4262 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4263 // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4264 bool colinearity(inters.areColinears());
4265 delete e1; delete e2;
4267 { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4269 { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4273 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4278 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4280 INTERP_KERNEL::Edge *ret=0;
4283 case INTERP_KERNEL::NORM_SEG2:
4285 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4288 case INTERP_KERNEL::NORM_SEG3:
4290 INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4291 INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4292 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4293 // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4294 bool colinearity=inters.areColinears();
4295 delete e1; delete e2;
4297 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4299 ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4300 mapp2[bg[2]].second=false;
4304 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4310 * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4311 * the global mesh 'mDesc'.
4312 * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4313 * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4315 INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4316 std::map<INTERP_KERNEL::Node *,int>& mapp)
4319 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.
4320 const double *coo=mDesc->getCoords()->getConstPointer();
4321 const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4322 const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4324 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4325 s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4326 for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4328 INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4329 mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4331 INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4332 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4334 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4335 ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4337 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4339 if((*it2).second.second)
4340 mapp[(*it2).second.first]=(*it2).first;
4341 ((*it2).second.first)->decrRef();
4346 INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4350 int locId=nodeId-offset2;
4351 return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4355 int locId=nodeId-offset1;
4356 return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4358 return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4362 * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4364 void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4365 const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4366 /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4368 for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4370 int eltId1=abs(*desc1)-1;
4371 for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4373 std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4374 if(it==mappRev.end())
4376 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4387 template<int SPACEDIM>
4388 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4389 double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4391 elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4392 int *eltsIndexPtr(eltsIndex->getPointer());
4393 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4394 const double *bbox(bboxArr->begin());
4395 int nbOfCells=getNumberOfCells();
4396 const int *conn=_nodal_connec->getConstPointer();
4397 const int *connI=_nodal_connec_index->getConstPointer();
4398 double bb[2*SPACEDIM];
4399 BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4400 for(int i=0;i<nbOfPoints;i++)
4402 eltsIndexPtr[i+1]=eltsIndexPtr[i];
4403 for(int j=0;j<SPACEDIM;j++)
4405 bb[2*j]=pos[SPACEDIM*i+j];
4406 bb[2*j+1]=pos[SPACEDIM*i+j];
4408 std::vector<int> candidates;
4409 myTree.getIntersectingElems(bb,candidates);
4410 for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4412 int sz(connI[(*iter)+1]-connI[*iter]-1);
4413 INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4415 if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4416 status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4420 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4421 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4422 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4423 std::vector<INTERP_KERNEL::Node *> nodes(sz);
4424 INTERP_KERNEL::QuadraticPolygon *pol(0);
4425 for(int j=0;j<sz;j++)
4427 int nodeId(conn[connI[*iter]+1+j]);
4428 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4430 if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4431 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4433 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4434 INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4435 double a(0.),b(0.),c(0.);
4436 a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4437 status=pol->isInOrOut2(n);
4438 delete pol; n->decrRef();
4442 eltsIndexPtr[i+1]++;
4443 elts->pushBackSilent(*iter);
4449 * Finds cells in contact with several balls (i.e. points with precision).
4450 * This method is an extension of getCellContainingPoint() and
4451 * getCellsContainingPoint() for the case of multiple points.
4452 * 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.
4453 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4454 * \param [in] pos - an array of coordinates of points in full interlace mode :
4455 * X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4456 * this->getSpaceDimension() * \a nbOfPoints
4457 * \param [in] nbOfPoints - number of points to locate within \a this mesh.
4458 * \param [in] eps - radius of balls (i.e. the precision).
4459 * \param [out] elts - vector returning ids of found cells.
4460 * \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4461 * dividing cell ids in \a elts into groups each referring to one
4462 * point. Its every element (except the last one) is an index pointing to the
4463 * first id of a group of cells. For example cells in contact with the *i*-th
4464 * point are described by following range of indices:
4465 * [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4466 * \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4467 * Number of cells in contact with the *i*-th point is
4468 * \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4469 * \throw If the coordinates array is not set.
4470 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4472 * \if ENABLE_EXAMPLES
4473 * \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4474 * \ref py_mcumesh_getCellsContainingPoints "Here is a Python example".
4477 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4478 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4480 int spaceDim=getSpaceDimension();
4481 int mDim=getMeshDimension();
4486 const double *coords=_coords->getConstPointer();
4487 getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4494 throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4496 else if(spaceDim==2)
4500 const double *coords=_coords->getConstPointer();
4501 getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4504 throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4506 else if(spaceDim==1)
4510 const double *coords=_coords->getConstPointer();
4511 getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4514 throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4517 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4521 * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4522 * least two its edges intersect each other anywhere except their extremities. An
4523 * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4524 * \param [in,out] cells - a vector returning ids of the found cells. It is not
4525 * cleared before filling in.
4526 * \param [in] eps - precision.
4527 * \throw If \a this->getMeshDimension() != 2.
4528 * \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4530 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4532 const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4533 if(getMeshDimension()!=2)
4534 throw INTERP_KERNEL::Exception(msg);
4535 int spaceDim=getSpaceDimension();
4536 if(spaceDim!=2 && spaceDim!=3)
4537 throw INTERP_KERNEL::Exception(msg);
4538 const int *conn=_nodal_connec->getConstPointer();
4539 const int *connI=_nodal_connec_index->getConstPointer();
4540 int nbOfCells=getNumberOfCells();
4541 std::vector<double> cell2DinS2;
4542 for(int i=0;i<nbOfCells;i++)
4544 int offset=connI[i];
4545 int nbOfNodesForCell=connI[i+1]-offset-1;
4546 if(nbOfNodesForCell<=3)
4548 bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4549 project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4550 if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4557 * This method is typically requested to unbutterfly 2D linear cells in \b this.
4559 * 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.
4560 * 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.
4562 * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4563 * This convex envelop is computed using Jarvis march algorithm.
4564 * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4565 * 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)
4566 * 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.
4568 * \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.
4569 * \sa MEDCouplingUMesh::colinearize2D
4571 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4573 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4574 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D works only for meshDim=2 and spaceDim=2 !");
4575 checkFullyDefined();
4576 const double *coords=getCoords()->getConstPointer();
4577 int nbOfCells=getNumberOfCells();
4578 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4579 nodalConnecIndexOut->alloc(nbOfCells+1,1);
4580 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4581 int *workIndexOut=nodalConnecIndexOut->getPointer();
4583 const int *nodalConnecIn=_nodal_connec->getConstPointer();
4584 const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4585 std::set<INTERP_KERNEL::NormalizedCellType> types;
4586 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4587 isChanged->alloc(0,1);
4588 for(int i=0;i<nbOfCells;i++,workIndexOut++)
4590 int pos=nodalConnecOut->getNumberOfTuples();
4591 if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4592 isChanged->pushBackSilent(i);
4593 types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4594 workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4596 if(isChanged->empty())
4598 setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4600 return isChanged.retn();
4604 * This method is \b NOT const because it can modify \a this.
4605 * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4606 * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4607 * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4608 * \b 1 for translation and rotation around point of 'mesh1D'.
4609 * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.
4611 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4613 checkFullyDefined();
4614 mesh1D->checkFullyDefined();
4615 if(!mesh1D->isContiguous1D())
4616 throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4617 if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4618 throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4619 if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4620 throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4621 if(mesh1D->getMeshDimension()!=1)
4622 throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4624 if(isPresenceOfQuadratic())
4626 if(mesh1D->isFullyQuadratic())
4629 throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4631 int oldNbOfNodes=getNumberOfNodes();
4632 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4637 newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4642 newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4646 throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4648 setCoords(newCoords);
4649 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4655 * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4656 * If it is not the case an exception will be thrown.
4657 * This method is non const because the coordinate of \a this can be appended with some new points issued from
4658 * intersection of plane defined by ('origin','vec').
4659 * This method has one in/out parameter : 'cut3DCurve'.
4660 * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4661 * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4662 * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4663 * This method will throw an exception if \a this contains a non linear segment.
4665 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4667 checkFullyDefined();
4668 if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4669 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4670 int ncells=getNumberOfCells();
4671 int nnodes=getNumberOfNodes();
4672 double vec2[3],vec3[3],vec4[3];
4673 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4675 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4676 vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4677 const int *conn=_nodal_connec->getConstPointer();
4678 const int *connI=_nodal_connec_index->getConstPointer();
4679 const double *coo=_coords->getConstPointer();
4680 std::vector<double> addCoo;
4681 for(int i=0;i<ncells;i++)
4683 if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4685 if(cut3DCurve[i]==-2)
4687 int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4688 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];
4689 double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4690 double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4691 if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4693 const double *st2=coo+3*st;
4694 vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4695 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]));
4696 if(pos>eps && pos<1-eps)
4698 int nNode=((int)addCoo.size())/3;
4699 vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4700 addCoo.insert(addCoo.end(),vec4,vec4+3);
4701 cut3DCurve[i]=nnodes+nNode;
4707 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4711 int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4712 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4713 coo2->alloc(newNbOfNodes,3);
4714 double *tmp=coo2->getPointer();
4715 tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4716 std::copy(addCoo.begin(),addCoo.end(),tmp);
4717 DataArrayDouble::SetArrayIn(coo2,_coords);
4722 * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4723 * \param mesh1D is the input 1D mesh used for translation computation.
4724 * \return newCoords new coords filled by this method.
4726 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4728 int oldNbOfNodes=getNumberOfNodes();
4729 int nbOf1DCells=mesh1D->getNumberOfCells();
4730 int spaceDim=getSpaceDimension();
4731 DataArrayDouble *ret=DataArrayDouble::New();
4732 std::vector<bool> isQuads;
4733 int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4734 ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4735 double *retPtr=ret->getPointer();
4736 const double *coords=getCoords()->getConstPointer();
4737 double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4739 std::vector<double> c;
4743 for(int i=0;i<nbOf1DCells;i++)
4746 mesh1D->getNodeIdsOfCell(i,v);
4748 mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4749 mesh1D->getCoordinatesOfNode(v[0],c);
4750 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4751 for(int j=0;j<oldNbOfNodes;j++)
4752 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4756 mesh1D->getCoordinatesOfNode(v[1],c);
4757 mesh1D->getCoordinatesOfNode(v[0],c);
4758 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4759 for(int j=0;j<oldNbOfNodes;j++)
4760 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4763 ret->copyStringInfoFrom(*getCoords());
4768 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4769 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4770 * \return newCoords new coords filled by this method.
4772 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4774 if(mesh1D->getSpaceDimension()==2)
4775 return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4776 if(mesh1D->getSpaceDimension()==3)
4777 return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4778 throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4782 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4783 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4784 * \return newCoords new coords filled by this method.
4786 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4789 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4790 int oldNbOfNodes=getNumberOfNodes();
4791 int nbOf1DCells=mesh1D->getNumberOfCells();
4793 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4794 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4795 int nbOfLevsInVec=nbOf1DCells+1;
4796 ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4797 double *retPtr=ret->getPointer();
4798 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4799 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4800 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4801 tmp->setCoords(tmp2);
4802 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4803 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4804 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4805 for(int i=1;i<nbOfLevsInVec;i++)
4807 const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4808 const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4809 const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4810 const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4811 tmp->translate(vec);
4812 double tmp3[2],radius,alpha,alpha0;
4813 const double *p0=i+1<nbOfLevsInVec?begin:third;
4814 const double *p1=i+1<nbOfLevsInVec?end:begin;
4815 const double *p2=i+1<nbOfLevsInVec?third:end;
4816 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4817 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]);
4818 double angle=acos(cosangle/(radius*radius));
4819 tmp->rotate(end,0,angle);
4820 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4826 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4827 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4828 * \return newCoords new coords filled by this method.
4830 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4833 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4834 int oldNbOfNodes=getNumberOfNodes();
4835 int nbOf1DCells=mesh1D->getNumberOfCells();
4837 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4838 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4839 int nbOfLevsInVec=nbOf1DCells+1;
4840 ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4841 double *retPtr=ret->getPointer();
4842 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4843 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4844 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4845 tmp->setCoords(tmp2);
4846 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4847 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4848 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4849 for(int i=1;i<nbOfLevsInVec;i++)
4851 const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4852 const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4853 const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4854 const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4855 tmp->translate(vec);
4856 double tmp3[2],radius,alpha,alpha0;
4857 const double *p0=i+1<nbOfLevsInVec?begin:third;
4858 const double *p1=i+1<nbOfLevsInVec?end:begin;
4859 const double *p2=i+1<nbOfLevsInVec?third:end;
4860 double vecPlane[3]={
4861 (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4862 (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4863 (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4865 double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4868 vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4869 double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4870 double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4872 double c2=cos(asin(s2));
4874 {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4875 {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4876 {-vec2[1]*s2, vec2[0]*s2, c2}
4878 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]};
4879 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]};
4880 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]};
4881 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4882 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]);
4883 double angle=acos(cosangle/(radius*radius));
4884 tmp->rotate(end,vecPlane,angle);
4886 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4892 * This method is private because not easy to use for end user. This method is const contrary to
4893 * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4894 * the coords sorted slice by slice.
4895 * \param isQuad specifies presence of quadratic cells.
4897 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4899 int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4900 int nbOf2DCells=getNumberOfCells();
4901 int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4902 MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4903 const int *conn=_nodal_connec->getConstPointer();
4904 const int *connI=_nodal_connec_index->getConstPointer();
4905 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4906 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4907 newConnI->alloc(nbOf3DCells+1,1);
4908 int *newConnIPtr=newConnI->getPointer();
4910 std::vector<int> newc;
4911 for(int j=0;j<nbOf2DCells;j++)
4913 AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4914 *newConnIPtr++=(int)newc.size();
4916 newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4917 int *newConnPtr=newConn->getPointer();
4918 int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4919 newConnIPtr=newConnI->getPointer();
4920 for(int iz=0;iz<nbOf1DCells;iz++)
4923 std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4924 for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4926 int icell=(int)(iter-newc.begin());
4927 if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4930 *newConnPtr=(*iter)+iz*deltaPerLev;
4935 *newConnPtr=(*iter);
4938 ret->setConnectivity(newConn,newConnI,true);
4939 ret->setCoords(getCoords());
4944 * Checks if \a this mesh is constituted by only quadratic cells.
4945 * \return bool - \c true if there are only quadratic cells in \a this mesh.
4946 * \throw If the coordinates array is not set.
4947 * \throw If the nodal connectivity of cells is not defined.
4949 bool MEDCouplingUMesh::isFullyQuadratic() const
4951 checkFullyDefined();
4953 int nbOfCells=getNumberOfCells();
4954 for(int i=0;i<nbOfCells && ret;i++)
4956 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4957 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4958 ret=cm.isQuadratic();
4964 * Checks if \a this mesh includes any quadratic cell.
4965 * \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4966 * \throw If the coordinates array is not set.
4967 * \throw If the nodal connectivity of cells is not defined.
4969 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4971 checkFullyDefined();
4973 int nbOfCells=getNumberOfCells();
4974 for(int i=0;i<nbOfCells && !ret;i++)
4976 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4977 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4978 ret=cm.isQuadratic();
4984 * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4985 * this mesh, it remains unchanged.
4986 * \throw If the coordinates array is not set.
4987 * \throw If the nodal connectivity of cells is not defined.
4989 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4991 checkFullyDefined();
4992 int nbOfCells=getNumberOfCells();
4994 const int *iciptr=_nodal_connec_index->getConstPointer();
4995 for(int i=0;i<nbOfCells;i++)
4997 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4998 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4999 if(cm.isQuadratic())
5001 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5002 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5003 if(!cml.isDynamic())
5004 delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
5006 delta+=(iciptr[i+1]-iciptr[i]-1)/2;
5011 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5012 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5013 const int *icptr=_nodal_connec->getConstPointer();
5014 newConn->alloc(getMeshLength()-delta,1);
5015 newConnI->alloc(nbOfCells+1,1);
5016 int *ocptr=newConn->getPointer();
5017 int *ociptr=newConnI->getPointer();
5020 for(int i=0;i<nbOfCells;i++,ociptr++)
5022 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
5023 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5024 if(!cm.isQuadratic())
5026 _types.insert(type);
5027 ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5028 ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5032 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5033 _types.insert(typel);
5034 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5035 int newNbOfNodes=cml.getNumberOfNodes();
5037 newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
5038 *ocptr++=(int)typel;
5039 ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5040 ociptr[1]=ociptr[0]+newNbOfNodes+1;
5043 setConnectivity(newConn,newConnI,false);
5047 * This method converts all linear cell in \a this to quadratic one.
5048 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5049 * 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)
5050 * 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.
5051 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5052 * end of the existing coordinates.
5054 * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5055 * corresponding quadratic cells. 1 is those creating the 'most' complex.
5056 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5058 * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5060 * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5062 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5064 DataArrayInt *conn=0,*connI=0;
5065 DataArrayDouble *coords=0;
5066 std::set<INTERP_KERNEL::NormalizedCellType> types;
5067 checkFullyDefined();
5068 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5069 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5070 int meshDim=getMeshDimension();
5071 switch(conversionType)
5077 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5078 connSafe=conn; connISafe=connI; coordsSafe=coords;
5081 ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5082 connSafe=conn; connISafe=connI; coordsSafe=coords;
5085 ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5086 connSafe=conn; connISafe=connI; coordsSafe=coords;
5089 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5097 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5098 connSafe=conn; connISafe=connI; coordsSafe=coords;
5101 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5102 connSafe=conn; connISafe=connI; coordsSafe=coords;
5105 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5106 connSafe=conn; connISafe=connI; coordsSafe=coords;
5109 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5114 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5116 setConnectivity(connSafe,connISafe,false);
5118 setCoords(coordsSafe);
5124 * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
5125 * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
5126 * The nodes to be added in those 2D cells are defined by the pair of \a nodeIdsToAdd and \a nodeIdsIndexToAdd.
5127 * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
5128 * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
5129 * This method can be seen as the opposite method of colinearize2D.
5130 * 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
5131 * to avoid to modify the numbering of existing nodes.
5133 * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
5134 * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
5135 * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
5136 * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
5137 * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
5138 * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
5139 * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
5141 * \sa buildDescendingConnectivity2
5143 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
5144 const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
5146 if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
5147 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
5148 nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
5149 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
5150 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
5151 if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
5152 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
5153 //DataArrayInt *out0(0),*outi0(0);
5154 //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
5155 //MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s(out0),outi0s(outi0);
5156 //out0s=out0s->buildUnique(); out0s->sort(true);
5161 * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5162 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5163 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5165 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5167 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5168 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5169 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5170 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5171 int nbOfCells=getNumberOfCells();
5172 int nbOfNodes=getNumberOfNodes();
5173 const int *cPtr=_nodal_connec->getConstPointer();
5174 const int *icPtr=_nodal_connec_index->getConstPointer();
5175 int lastVal=0,offset=nbOfNodes;
5176 for(int i=0;i<nbOfCells;i++,icPtr++)
5178 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5179 if(type==INTERP_KERNEL::NORM_SEG2)
5181 types.insert(INTERP_KERNEL::NORM_SEG3);
5182 newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5183 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5184 newConn->pushBackSilent(offset++);
5186 newConnI->pushBackSilent(lastVal);
5187 ret->pushBackSilent(i);
5192 lastVal+=(icPtr[1]-icPtr[0]);
5193 newConnI->pushBackSilent(lastVal);
5194 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5197 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5198 coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5202 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
5204 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5205 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5206 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5208 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5209 DataArrayInt *conn1D=0,*conn1DI=0;
5210 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5211 DataArrayDouble *coordsTmp=0;
5212 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5213 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5214 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5215 const int *c1DPtr=conn1D->begin();
5216 const int *c1DIPtr=conn1DI->begin();
5217 int nbOfCells=getNumberOfCells();
5218 const int *cPtr=_nodal_connec->getConstPointer();
5219 const int *icPtr=_nodal_connec_index->getConstPointer();
5221 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5223 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5224 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5225 if(!cm.isQuadratic())
5227 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5228 types.insert(typ2); newConn->pushBackSilent(typ2);
5229 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5230 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5231 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5232 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5233 newConnI->pushBackSilent(lastVal);
5234 ret->pushBackSilent(i);
5239 lastVal+=(icPtr[1]-icPtr[0]);
5240 newConnI->pushBackSilent(lastVal);
5241 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5244 conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5249 * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5250 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5251 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5253 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5255 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5256 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5257 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5260 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5262 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5263 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5265 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5266 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5267 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5269 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5270 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5271 DataArrayInt *conn1D=0,*conn1DI=0;
5272 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5273 DataArrayDouble *coordsTmp=0;
5274 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5275 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5276 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5277 const int *c1DPtr=conn1D->begin();
5278 const int *c1DIPtr=conn1DI->begin();
5279 int nbOfCells=getNumberOfCells();
5280 const int *cPtr=_nodal_connec->getConstPointer();
5281 const int *icPtr=_nodal_connec_index->getConstPointer();
5282 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5283 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5285 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5286 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5287 if(!cm.isQuadratic())
5289 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5290 types.insert(typ2); newConn->pushBackSilent(typ2);
5291 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5292 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5293 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5294 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5295 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5296 newConnI->pushBackSilent(lastVal);
5297 ret->pushBackSilent(i);
5302 lastVal+=(icPtr[1]-icPtr[0]);
5303 newConnI->pushBackSilent(lastVal);
5304 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5307 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5308 coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5313 * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5314 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5315 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5317 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5319 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5320 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5321 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5324 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5326 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5327 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5328 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5329 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5331 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5332 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5333 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5335 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5336 const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5337 DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5338 std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5339 DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5340 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5341 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5342 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5343 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5344 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5345 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5346 const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5347 int nbOfCells=getNumberOfCells();
5348 const int *cPtr=_nodal_connec->getConstPointer();
5349 const int *icPtr=_nodal_connec_index->getConstPointer();
5350 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5351 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5353 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5354 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5355 if(!cm.isQuadratic())
5357 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5358 if(typ2==INTERP_KERNEL::NORM_ERROR)
5360 std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5361 throw INTERP_KERNEL::Exception(oss.str().c_str());
5363 types.insert(typ2); newConn->pushBackSilent(typ2);
5364 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5365 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5366 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5367 for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5369 int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5370 int tmpPos=newConn->getNumberOfTuples();
5371 newConn->pushBackSilent(nodeId2);
5372 ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5374 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5375 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5376 newConnI->pushBackSilent(lastVal);
5377 ret->pushBackSilent(i);
5382 lastVal+=(icPtr[1]-icPtr[0]);
5383 newConnI->pushBackSilent(lastVal);
5384 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5387 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5388 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5389 coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5390 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5391 std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5392 int *c=newConn->getPointer();
5393 const int *cI(newConnI->begin());
5394 for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5395 c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5396 offset=coordsTmp2Safe->getNumberOfTuples();
5397 for(const int *elt=ret->begin();elt!=ret->end();elt++)
5398 c[cI[(*elt)+1]-1]+=offset;
5399 coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5404 * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5405 * so that the number of cells remains the same. Quadratic faces are converted to
5406 * polygons. This method works only for 2D meshes in
5407 * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5408 * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5409 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5410 * \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5411 * a polylinized edge constituting the input polygon.
5412 * \throw If the coordinates array is not set.
5413 * \throw If the nodal connectivity of cells is not defined.
5414 * \throw If \a this->getMeshDimension() != 2.
5415 * \throw If \a this->getSpaceDimension() != 2.
5417 void MEDCouplingUMesh::tessellate2D(double eps)
5419 checkFullyDefined();
5420 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
5421 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5422 double epsa=fabs(eps);
5423 if(epsa<std::numeric_limits<double>::min())
5424 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 !");
5425 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5426 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5427 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5428 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5429 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5430 revDesc1=0; revDescIndx1=0;
5431 mDesc->tessellate2DCurve(eps);
5432 subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5433 setCoords(mDesc->getCoords());
5437 * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5438 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5439 * \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5440 * a sub-divided edge.
5441 * \throw If the coordinates array is not set.
5442 * \throw If the nodal connectivity of cells is not defined.
5443 * \throw If \a this->getMeshDimension() != 1.
5444 * \throw If \a this->getSpaceDimension() != 2.
5446 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5448 checkFullyDefined();
5449 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5450 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5451 double epsa=fabs(eps);
5452 if(epsa<std::numeric_limits<double>::min())
5453 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 !");
5454 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5455 int nbCells=getNumberOfCells();
5456 int nbNodes=getNumberOfNodes();
5457 const int *conn=_nodal_connec->getConstPointer();
5458 const int *connI=_nodal_connec_index->getConstPointer();
5459 const double *coords=_coords->getConstPointer();
5460 std::vector<double> addCoo;
5461 std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5462 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5463 newConnI->alloc(nbCells+1,1);
5464 int *newConnIPtr=newConnI->getPointer();
5467 INTERP_KERNEL::Node *tmp2[3];
5468 std::set<INTERP_KERNEL::NormalizedCellType> types;
5469 for(int i=0;i<nbCells;i++,newConnIPtr++)
5471 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5472 if(cm.isQuadratic())
5473 {//assert(connI[i+1]-connI[i]-1==3)
5474 tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5475 tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5476 tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5477 tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5478 INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5481 eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5482 types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5484 newConnIPtr[1]=(int)newConn.size();
5488 types.insert(INTERP_KERNEL::NORM_SEG2);
5489 newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5490 newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5491 newConnIPtr[1]=newConnIPtr[0]+3;
5496 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5497 newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5498 newConnIPtr[1]=newConnIPtr[0]+3;
5501 if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5504 DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5505 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5506 newConnArr->alloc((int)newConn.size(),1);
5507 std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5508 DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5509 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5510 newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5511 double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5512 std::copy(addCoo.begin(),addCoo.end(),work);
5513 DataArrayDouble::SetArrayIn(newCoords,_coords);
5518 * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5519 * In addition, returns an array mapping new cells to old ones. <br>
5520 * This method typically increases the number of cells in \a this mesh
5521 * but the number of nodes remains \b unchanged.
5522 * That's why the 3D splitting policies
5523 * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5524 * \param [in] policy - specifies a pattern used for splitting.
5525 * The semantic of \a policy is:
5526 * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5527 * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5528 * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8 into 5 TETRA4 (for 3D mesh only).
5529 * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8 into 6 TETRA4 (for 3D mesh only).
5530 * \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5531 * an id of old cell producing it. The caller is to delete this array using
5532 * decrRef() as it is no more needed.
5533 * \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5534 * \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5535 * and \a this->getMeshDimension() != 3.
5536 * \throw If \a policy is not one of the four discussed above.
5537 * \throw If the nodal connectivity of cells is not defined.
5538 * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5540 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5545 return simplexizePol0();
5547 return simplexizePol1();
5548 case (int) INTERP_KERNEL::PLANAR_FACE_5:
5549 return simplexizePlanarFace5();
5550 case (int) INTERP_KERNEL::PLANAR_FACE_6:
5551 return simplexizePlanarFace6();
5553 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)");
5558 * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5559 * - 1D: INTERP_KERNEL::NORM_SEG2
5560 * - 2D: INTERP_KERNEL::NORM_TRI3
5561 * - 3D: INTERP_KERNEL::NORM_TETRA4.
5563 * This method is useful for users that need to use P1 field services as
5564 * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5565 * All these methods need mesh support containing only simplex cells.
5566 * \return bool - \c true if there are only simplex cells in \a this mesh.
5567 * \throw If the coordinates array is not set.
5568 * \throw If the nodal connectivity of cells is not defined.
5569 * \throw If \a this->getMeshDimension() < 1.
5571 bool MEDCouplingUMesh::areOnlySimplexCells() const
5573 checkFullyDefined();
5574 int mdim=getMeshDimension();
5575 if(mdim<1 || mdim>3)
5576 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5577 int nbCells=getNumberOfCells();
5578 const int *conn=_nodal_connec->getConstPointer();
5579 const int *connI=_nodal_connec_index->getConstPointer();
5580 for(int i=0;i<nbCells;i++)
5582 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5590 * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5592 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5594 checkConnectivityFullyDefined();
5595 if(getMeshDimension()!=2)
5596 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5597 int nbOfCells=getNumberOfCells();
5598 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5599 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5600 ret->alloc(nbOfCells+nbOfCutCells,1);
5601 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5602 int *retPt=ret->getPointer();
5603 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5604 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5605 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5606 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5607 int *pt=newConn->getPointer();
5608 int *ptI=newConnI->getPointer();
5610 const int *oldc=_nodal_connec->getConstPointer();
5611 const int *ci=_nodal_connec_index->getConstPointer();
5612 for(int i=0;i<nbOfCells;i++,ci++)
5614 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5616 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5617 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5618 pt=std::copy(tmp,tmp+8,pt);
5627 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5628 ptI[1]=ptI[0]+ci[1]-ci[0];
5633 _nodal_connec->decrRef();
5634 _nodal_connec=newConn.retn();
5635 _nodal_connec_index->decrRef();
5636 _nodal_connec_index=newConnI.retn();
5643 * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5645 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5647 checkConnectivityFullyDefined();
5648 if(getMeshDimension()!=2)
5649 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5650 int nbOfCells=getNumberOfCells();
5651 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5652 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5653 ret->alloc(nbOfCells+nbOfCutCells,1);
5654 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5655 int *retPt=ret->getPointer();
5656 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5657 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5658 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5659 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5660 int *pt=newConn->getPointer();
5661 int *ptI=newConnI->getPointer();
5663 const int *oldc=_nodal_connec->getConstPointer();
5664 const int *ci=_nodal_connec_index->getConstPointer();
5665 for(int i=0;i<nbOfCells;i++,ci++)
5667 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5669 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5670 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5671 pt=std::copy(tmp,tmp+8,pt);
5680 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5681 ptI[1]=ptI[0]+ci[1]-ci[0];
5686 _nodal_connec->decrRef();
5687 _nodal_connec=newConn.retn();
5688 _nodal_connec_index->decrRef();
5689 _nodal_connec_index=newConnI.retn();
5696 * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5698 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5700 checkConnectivityFullyDefined();
5701 if(getMeshDimension()!=3)
5702 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5703 int nbOfCells=getNumberOfCells();
5704 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5705 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5706 ret->alloc(nbOfCells+4*nbOfCutCells,1);
5707 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5708 int *retPt=ret->getPointer();
5709 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5710 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5711 newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5712 newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5713 int *pt=newConn->getPointer();
5714 int *ptI=newConnI->getPointer();
5716 const int *oldc=_nodal_connec->getConstPointer();
5717 const int *ci=_nodal_connec_index->getConstPointer();
5718 for(int i=0;i<nbOfCells;i++,ci++)
5720 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5722 for(int j=0;j<5;j++,pt+=5,ptI++)
5724 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5725 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];
5732 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5733 ptI[1]=ptI[0]+ci[1]-ci[0];
5738 _nodal_connec->decrRef();
5739 _nodal_connec=newConn.retn();
5740 _nodal_connec_index->decrRef();
5741 _nodal_connec_index=newConnI.retn();
5748 * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5750 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5752 checkConnectivityFullyDefined();
5753 if(getMeshDimension()!=3)
5754 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5755 int nbOfCells=getNumberOfCells();
5756 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5757 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5758 ret->alloc(nbOfCells+5*nbOfCutCells,1);
5759 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5760 int *retPt=ret->getPointer();
5761 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5762 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5763 newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5764 newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5765 int *pt=newConn->getPointer();
5766 int *ptI=newConnI->getPointer();
5768 const int *oldc=_nodal_connec->getConstPointer();
5769 const int *ci=_nodal_connec_index->getConstPointer();
5770 for(int i=0;i<nbOfCells;i++,ci++)
5772 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5774 for(int j=0;j<6;j++,pt+=5,ptI++)
5776 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5777 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];
5784 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5785 ptI[1]=ptI[0]+ci[1]-ci[0];
5790 _nodal_connec->decrRef();
5791 _nodal_connec=newConn.retn();
5792 _nodal_connec_index->decrRef();
5793 _nodal_connec_index=newConnI.retn();
5800 * 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.
5801 * This method completly ignore coordinates.
5802 * \param nodeSubdived is the nodal connectivity of subdivision of edges
5803 * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5804 * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5805 * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5807 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5809 checkFullyDefined();
5810 if(getMeshDimension()!=2)
5811 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5812 int nbOfCells=getNumberOfCells();
5813 int *connI=_nodal_connec_index->getPointer();
5815 for(int i=0;i<nbOfCells;i++,connI++)
5817 int offset=descIndex[i];
5818 int nbOfEdges=descIndex[i+1]-offset;
5820 bool ddirect=desc[offset+nbOfEdges-1]>0;
5821 int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5822 int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5823 for(int j=0;j<nbOfEdges;j++)
5825 bool direct=desc[offset+j]>0;
5826 int edgeId=std::abs(desc[offset+j])-1;
5827 if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5829 int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5830 int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5831 int ref2=direct?id1:id2;
5834 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5835 newConnLgth+=nbOfSubNodes-1;
5840 std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5841 throw INTERP_KERNEL::Exception(oss.str().c_str());
5846 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5849 newConnLgth++;//+1 is for cell type
5850 connI[1]=newConnLgth;
5853 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5854 newConn->alloc(newConnLgth,1);
5855 int *work=newConn->getPointer();
5856 for(int i=0;i<nbOfCells;i++)
5858 *work++=INTERP_KERNEL::NORM_POLYGON;
5859 int offset=descIndex[i];
5860 int nbOfEdges=descIndex[i+1]-offset;
5861 for(int j=0;j<nbOfEdges;j++)
5863 bool direct=desc[offset+j]>0;
5864 int edgeId=std::abs(desc[offset+j])-1;
5866 work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5869 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5870 std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5871 work=std::copy(it,it+nbOfSubNodes-1,work);
5875 DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5878 _types.insert(INTERP_KERNEL::NORM_POLYGON);
5882 * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5883 * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5884 * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5885 * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5886 * so it can be useful to call mergeNodes() before calling this method.
5887 * \throw If \a this->getMeshDimension() <= 1.
5888 * \throw If the coordinates array is not set.
5889 * \throw If the nodal connectivity of cells is not defined.
5891 void MEDCouplingUMesh::convertDegeneratedCells()
5893 checkFullyDefined();
5894 if(getMeshDimension()<=1)
5895 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5896 int nbOfCells=getNumberOfCells();
5899 int initMeshLgth=getMeshLength();
5900 int *conn=_nodal_connec->getPointer();
5901 int *index=_nodal_connec_index->getPointer();
5905 for(int i=0;i<nbOfCells;i++)
5907 lgthOfCurCell=index[i+1]-posOfCurCell;
5908 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5910 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5911 conn+newPos+1,newLgth);
5912 conn[newPos]=newType;
5914 posOfCurCell=index[i+1];
5917 if(newPos!=initMeshLgth)
5918 _nodal_connec->reAlloc(newPos);
5923 * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5924 * A cell is considered to be oriented correctly if an angle between its
5925 * normal vector and a given vector is less than \c PI / \c 2.
5926 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5928 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5930 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5931 * is not cleared before filling in.
5932 * \throw If \a this->getMeshDimension() != 2.
5933 * \throw If \a this->getSpaceDimension() != 3.
5935 * \if ENABLE_EXAMPLES
5936 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5937 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5940 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
5942 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5943 throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5944 int nbOfCells=getNumberOfCells();
5945 const int *conn=_nodal_connec->getConstPointer();
5946 const int *connI=_nodal_connec_index->getConstPointer();
5947 const double *coordsPtr=_coords->getConstPointer();
5948 for(int i=0;i<nbOfCells;i++)
5950 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5951 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5953 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5954 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5961 * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5962 * considered to be oriented correctly if an angle between its normal vector and a
5963 * given vector is less than \c PI / \c 2.
5964 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5966 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5968 * \throw If \a this->getMeshDimension() != 2.
5969 * \throw If \a this->getSpaceDimension() != 3.
5971 * \if ENABLE_EXAMPLES
5972 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5973 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5976 * \sa changeOrientationOfCells
5978 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
5980 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5981 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5982 int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
5983 const int *connI(_nodal_connec_index->getConstPointer());
5984 const double *coordsPtr(_coords->getConstPointer());
5985 bool isModified(false);
5986 for(int i=0;i<nbOfCells;i++)
5988 INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5989 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5991 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
5992 bool isQuadratic(cm.isQuadratic());
5993 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5996 cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6001 _nodal_connec->declareAsNew();
6006 * This method change the orientation of cells in \a this without any consideration of coordinates. Only connectivity is impacted.
6008 * \sa orientCorrectly2DCells
6010 void MEDCouplingUMesh::changeOrientationOfCells()
6012 int mdim(getMeshDimension());
6013 if(mdim!=2 && mdim!=1)
6014 throw INTERP_KERNEL::Exception("Invalid mesh to apply changeOrientationOfCells on it : must be meshDim==2 or meshDim==1 !");
6015 int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6016 const int *connI(_nodal_connec_index->getConstPointer());
6019 for(int i=0;i<nbOfCells;i++)
6021 INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6022 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6023 cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6028 for(int i=0;i<nbOfCells;i++)
6030 INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6031 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6032 cm.changeOrientationOf1D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6038 * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
6039 * oriented facets. The normal vector of the facet should point out of the cell.
6040 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6041 * is not cleared before filling in.
6042 * \throw If \a this->getMeshDimension() != 3.
6043 * \throw If \a this->getSpaceDimension() != 3.
6044 * \throw If the coordinates array is not set.
6045 * \throw If the nodal connectivity of cells is not defined.
6047 * \if ENABLE_EXAMPLES
6048 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6049 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6052 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
6054 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6055 throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
6056 int nbOfCells=getNumberOfCells();
6057 const int *conn=_nodal_connec->getConstPointer();
6058 const int *connI=_nodal_connec_index->getConstPointer();
6059 const double *coordsPtr=_coords->getConstPointer();
6060 for(int i=0;i<nbOfCells;i++)
6062 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6063 if(type==INTERP_KERNEL::NORM_POLYHED)
6065 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6072 * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6074 * \throw If \a this->getMeshDimension() != 3.
6075 * \throw If \a this->getSpaceDimension() != 3.
6076 * \throw If the coordinates array is not set.
6077 * \throw If the nodal connectivity of cells is not defined.
6078 * \throw If the reparation fails.
6080 * \if ENABLE_EXAMPLES
6081 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6082 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6084 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6086 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
6088 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6089 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6090 int nbOfCells=getNumberOfCells();
6091 int *conn=_nodal_connec->getPointer();
6092 const int *connI=_nodal_connec_index->getConstPointer();
6093 const double *coordsPtr=_coords->getConstPointer();
6094 for(int i=0;i<nbOfCells;i++)
6096 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6097 if(type==INTERP_KERNEL::NORM_POLYHED)
6101 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6102 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6104 catch(INTERP_KERNEL::Exception& e)
6106 std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6107 throw INTERP_KERNEL::Exception(oss.str().c_str());
6115 * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6116 * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6117 * according to which the first facet of the cell should be oriented to have the normal vector
6118 * pointing out of cell.
6119 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6120 * cells. The caller is to delete this array using decrRef() as it is no more
6122 * \throw If \a this->getMeshDimension() != 3.
6123 * \throw If \a this->getSpaceDimension() != 3.
6124 * \throw If the coordinates array is not set.
6125 * \throw If the nodal connectivity of cells is not defined.
6127 * \if ENABLE_EXAMPLES
6128 * \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6129 * \ref py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6131 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6133 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6135 const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6136 if(getMeshDimension()!=3)
6137 throw INTERP_KERNEL::Exception(msg);
6138 int spaceDim=getSpaceDimension();
6140 throw INTERP_KERNEL::Exception(msg);
6142 int nbOfCells=getNumberOfCells();
6143 int *conn=_nodal_connec->getPointer();
6144 const int *connI=_nodal_connec_index->getConstPointer();
6145 const double *coo=getCoords()->getConstPointer();
6146 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6147 for(int i=0;i<nbOfCells;i++)
6149 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6150 if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6152 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6154 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6155 cells->pushBackSilent(i);
6159 return cells.retn();
6163 * This method is a faster method to correct orientation of all 3D cells in \a this.
6164 * 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.
6165 * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6167 * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6168 * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons,
6170 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6172 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6173 throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6174 int nbOfCells=getNumberOfCells();
6175 int *conn=_nodal_connec->getPointer();
6176 const int *connI=_nodal_connec_index->getConstPointer();
6177 const double *coordsPtr=_coords->getConstPointer();
6178 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6179 for(int i=0;i<nbOfCells;i++)
6181 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6184 case INTERP_KERNEL::NORM_TETRA4:
6186 if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6188 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6189 ret->pushBackSilent(i);
6193 case INTERP_KERNEL::NORM_PYRA5:
6195 if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6197 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6198 ret->pushBackSilent(i);
6202 case INTERP_KERNEL::NORM_PENTA6:
6203 case INTERP_KERNEL::NORM_HEXA8:
6204 case INTERP_KERNEL::NORM_HEXGP12:
6206 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6208 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6209 ret->pushBackSilent(i);
6213 case INTERP_KERNEL::NORM_POLYHED:
6215 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6217 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6218 ret->pushBackSilent(i);
6223 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 !");
6231 * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6232 * If it is not the case an exception will be thrown.
6233 * This method is fast because the first cell of \a this is used to compute the plane.
6234 * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6235 * \param pos output of size at least 3 used to store a point owned of searched plane.
6237 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6239 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6240 throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6241 const int *conn=_nodal_connec->getConstPointer();
6242 const int *connI=_nodal_connec_index->getConstPointer();
6243 const double *coordsPtr=_coords->getConstPointer();
6244 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6245 std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6249 * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6250 * cells. Currently cells of the following types are treated:
6251 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6252 * For a cell of other type an exception is thrown.
6253 * Space dimension of a 2D mesh can be either 2 or 3.
6254 * The Edge Ratio of a cell \f$t\f$ is:
6255 * \f$\frac{|t|_\infty}{|t|_0}\f$,
6256 * where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6257 * the smallest edge lengths of \f$t\f$.
6258 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6259 * cells and one time, lying on \a this mesh. The caller is to delete this
6260 * field using decrRef() as it is no more needed.
6261 * \throw If the coordinates array is not set.
6262 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6263 * \throw If the connectivity data array has more than one component.
6264 * \throw If the connectivity data array has a named component.
6265 * \throw If the connectivity index data array has more than one component.
6266 * \throw If the connectivity index data array has a named component.
6267 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6268 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6269 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6271 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6274 int spaceDim=getSpaceDimension();
6275 int meshDim=getMeshDimension();
6276 if(spaceDim!=2 && spaceDim!=3)
6277 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6278 if(meshDim!=2 && meshDim!=3)
6279 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6280 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6282 int nbOfCells=getNumberOfCells();
6283 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6284 arr->alloc(nbOfCells,1);
6285 double *pt=arr->getPointer();
6286 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6287 const int *conn=_nodal_connec->getConstPointer();
6288 const int *connI=_nodal_connec_index->getConstPointer();
6289 const double *coo=_coords->getConstPointer();
6291 for(int i=0;i<nbOfCells;i++,pt++)
6293 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6296 case INTERP_KERNEL::NORM_TRI3:
6298 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6299 *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6302 case INTERP_KERNEL::NORM_QUAD4:
6304 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6305 *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6308 case INTERP_KERNEL::NORM_TETRA4:
6310 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6311 *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6315 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6317 conn+=connI[i+1]-connI[i];
6319 ret->setName("EdgeRatio");
6320 ret->synchronizeTimeWithSupport();
6325 * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6326 * cells. Currently cells of the following types are treated:
6327 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6328 * For a cell of other type an exception is thrown.
6329 * Space dimension of a 2D mesh can be either 2 or 3.
6330 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6331 * cells and one time, lying on \a this mesh. The caller is to delete this
6332 * field using decrRef() as it is no more needed.
6333 * \throw If the coordinates array is not set.
6334 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6335 * \throw If the connectivity data array has more than one component.
6336 * \throw If the connectivity data array has a named component.
6337 * \throw If the connectivity index data array has more than one component.
6338 * \throw If the connectivity index data array has a named component.
6339 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6340 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6341 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6343 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6346 int spaceDim=getSpaceDimension();
6347 int meshDim=getMeshDimension();
6348 if(spaceDim!=2 && spaceDim!=3)
6349 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6350 if(meshDim!=2 && meshDim!=3)
6351 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6352 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6354 int nbOfCells=getNumberOfCells();
6355 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6356 arr->alloc(nbOfCells,1);
6357 double *pt=arr->getPointer();
6358 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6359 const int *conn=_nodal_connec->getConstPointer();
6360 const int *connI=_nodal_connec_index->getConstPointer();
6361 const double *coo=_coords->getConstPointer();
6363 for(int i=0;i<nbOfCells;i++,pt++)
6365 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6368 case INTERP_KERNEL::NORM_TRI3:
6370 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6371 *pt=INTERP_KERNEL::triAspectRatio(tmp);
6374 case INTERP_KERNEL::NORM_QUAD4:
6376 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6377 *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6380 case INTERP_KERNEL::NORM_TETRA4:
6382 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6383 *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6387 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6389 conn+=connI[i+1]-connI[i];
6391 ret->setName("AspectRatio");
6392 ret->synchronizeTimeWithSupport();
6397 * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6398 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6399 * treated: INTERP_KERNEL::NORM_QUAD4.
6400 * For a cell of other type an exception is thrown.
6401 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6402 * cells and one time, lying on \a this mesh. The caller is to delete this
6403 * field using decrRef() as it is no more needed.
6404 * \throw If the coordinates array is not set.
6405 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6406 * \throw If the connectivity data array has more than one component.
6407 * \throw If the connectivity data array has a named component.
6408 * \throw If the connectivity index data array has more than one component.
6409 * \throw If the connectivity index data array has a named component.
6410 * \throw If \a this->getMeshDimension() != 2.
6411 * \throw If \a this->getSpaceDimension() != 3.
6412 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6414 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6417 int spaceDim=getSpaceDimension();
6418 int meshDim=getMeshDimension();
6420 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6422 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6423 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6425 int nbOfCells=getNumberOfCells();
6426 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6427 arr->alloc(nbOfCells,1);
6428 double *pt=arr->getPointer();
6429 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6430 const int *conn=_nodal_connec->getConstPointer();
6431 const int *connI=_nodal_connec_index->getConstPointer();
6432 const double *coo=_coords->getConstPointer();
6434 for(int i=0;i<nbOfCells;i++,pt++)
6436 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6439 case INTERP_KERNEL::NORM_QUAD4:
6441 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6442 *pt=INTERP_KERNEL::quadWarp(tmp);
6446 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6448 conn+=connI[i+1]-connI[i];
6450 ret->setName("Warp");
6451 ret->synchronizeTimeWithSupport();
6457 * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6458 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6459 * treated: INTERP_KERNEL::NORM_QUAD4.
6460 * For a cell of other type an exception is thrown.
6461 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6462 * cells and one time, lying on \a this mesh. The caller is to delete this
6463 * field using decrRef() as it is no more needed.
6464 * \throw If the coordinates array is not set.
6465 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6466 * \throw If the connectivity data array has more than one component.
6467 * \throw If the connectivity data array has a named component.
6468 * \throw If the connectivity index data array has more than one component.
6469 * \throw If the connectivity index data array has a named component.
6470 * \throw If \a this->getMeshDimension() != 2.
6471 * \throw If \a this->getSpaceDimension() != 3.
6472 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6474 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6477 int spaceDim=getSpaceDimension();
6478 int meshDim=getMeshDimension();
6480 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6482 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6483 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6485 int nbOfCells=getNumberOfCells();
6486 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6487 arr->alloc(nbOfCells,1);
6488 double *pt=arr->getPointer();
6489 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6490 const int *conn=_nodal_connec->getConstPointer();
6491 const int *connI=_nodal_connec_index->getConstPointer();
6492 const double *coo=_coords->getConstPointer();
6494 for(int i=0;i<nbOfCells;i++,pt++)
6496 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6499 case INTERP_KERNEL::NORM_QUAD4:
6501 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6502 *pt=INTERP_KERNEL::quadSkew(tmp);
6506 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6508 conn+=connI[i+1]-connI[i];
6510 ret->setName("Skew");
6511 ret->synchronizeTimeWithSupport();
6516 * This method aggregate the bbox of each cell and put it into bbox parameter.
6518 * \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)
6519 * For all other cases this input parameter is ignored.
6520 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6522 * \throw If \a this is not fully set (coordinates and connectivity).
6523 * \throw If a cell in \a this has no valid nodeId.
6524 * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6526 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6528 int mDim(getMeshDimension()),sDim(getSpaceDimension());
6529 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.
6530 return getBoundingBoxForBBTreeFast();
6531 if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6533 bool presenceOfQuadratic(false);
6534 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6536 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6537 if(cm.isQuadratic())
6538 presenceOfQuadratic=true;
6540 if(!presenceOfQuadratic)
6541 return getBoundingBoxForBBTreeFast();
6542 if(mDim==2 && sDim==2)
6543 return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6545 return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6547 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) !");
6551 * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6552 * So meshes having quadratic cells the computed bounding boxes can be invalid !
6554 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6556 * \throw If \a this is not fully set (coordinates and connectivity).
6557 * \throw If a cell in \a this has no valid nodeId.
6559 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6561 checkFullyDefined();
6562 int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6563 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6564 double *bbox(ret->getPointer());
6565 for(int i=0;i<nbOfCells*spaceDim;i++)
6567 bbox[2*i]=std::numeric_limits<double>::max();
6568 bbox[2*i+1]=-std::numeric_limits<double>::max();
6570 const double *coordsPtr(_coords->getConstPointer());
6571 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6572 for(int i=0;i<nbOfCells;i++)
6574 int offset=connI[i]+1;
6575 int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6576 for(int j=0;j<nbOfNodesForCell;j++)
6578 int nodeId=conn[offset+j];
6579 if(nodeId>=0 && nodeId<nbOfNodes)
6581 for(int k=0;k<spaceDim;k++)
6583 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6584 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6591 std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6592 throw INTERP_KERNEL::Exception(oss.str().c_str());
6599 * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6600 * useful for 2D meshes having quadratic cells
6601 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6602 * the two extremities of the arc of circle).
6604 * \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)
6605 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6606 * \throw If \a this is not fully defined.
6607 * \throw If \a this is not a mesh with meshDimension equal to 2.
6608 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6609 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6611 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6613 checkFullyDefined();
6614 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6615 if(spaceDim!=2 || mDim!=2)
6616 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!");
6617 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6618 double *bbox(ret->getPointer());
6619 const double *coords(_coords->getConstPointer());
6620 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6621 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6623 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6624 int sz(connI[1]-connI[0]-1);
6625 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6626 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6627 INTERP_KERNEL::QuadraticPolygon *pol(0);
6628 for(int j=0;j<sz;j++)
6630 int nodeId(conn[*connI+1+j]);
6631 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6633 if(!cm.isQuadratic())
6634 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6636 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6637 INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6638 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax();
6644 * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6645 * useful for 2D meshes having quadratic cells
6646 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6647 * the two extremities of the arc of circle).
6649 * \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)
6650 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6651 * \throw If \a this is not fully defined.
6652 * \throw If \a this is not a mesh with meshDimension equal to 1.
6653 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6654 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6656 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6658 checkFullyDefined();
6659 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6660 if(spaceDim!=2 || mDim!=1)
6661 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!");
6662 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6663 double *bbox(ret->getPointer());
6664 const double *coords(_coords->getConstPointer());
6665 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6666 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6668 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6669 int sz(connI[1]-connI[0]-1);
6670 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6671 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6672 INTERP_KERNEL::Edge *edge(0);
6673 for(int j=0;j<sz;j++)
6675 int nodeId(conn[*connI+1+j]);
6676 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6678 if(!cm.isQuadratic())
6679 edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6681 edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6682 const INTERP_KERNEL::Bounds& b(edge->getBounds());
6683 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6690 namespace ParaMEDMEMImpl
6695 ConnReader(const int *c, int val):_conn(c),_val(val) { }
6696 bool operator() (const int& pos) { return _conn[pos]!=_val; }
6705 ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6706 bool operator() (const int& pos) { return _conn[pos]==_val; }
6716 * This method expects that \a this is sorted by types. If not an exception will be thrown.
6717 * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6718 * \a this is composed in cell types.
6719 * The returned array is of size 3*n where n is the number of different types present in \a this.
6720 * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here.
6721 * This parameter is kept only for compatibility with other methode listed above.
6723 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6725 checkConnectivityFullyDefined();
6726 const int *conn=_nodal_connec->getConstPointer();
6727 const int *connI=_nodal_connec_index->getConstPointer();
6728 const int *work=connI;
6729 int nbOfCells=getNumberOfCells();
6730 std::size_t n=getAllGeoTypes().size();
6731 std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6732 std::set<INTERP_KERNEL::NormalizedCellType> types;
6733 for(std::size_t i=0;work!=connI+nbOfCells;i++)
6735 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6736 if(types.find(typ)!=types.end())
6738 std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6739 oss << " is not contiguous !";
6740 throw INTERP_KERNEL::Exception(oss.str().c_str());
6744 const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6745 ret[3*i+1]=(int)std::distance(work,work2);
6752 * This method is used to check that this has contiguous cell type in same order than described in \a code.
6753 * only for types cell, type node is not managed.
6754 * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6755 * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6756 * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6757 * If 2 or more same geometric type is in \a code and exception is thrown too.
6759 * This method firstly checks
6760 * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6761 * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6762 * an exception is thrown too.
6764 * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6765 * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown
6766 * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6768 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6771 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6772 std::size_t sz=code.size();
6775 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6776 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6778 bool isNoPflUsed=true;
6779 for(std::size_t i=0;i<n;i++)
6780 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6782 types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6784 if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6785 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6786 isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6789 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6792 if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6793 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6794 if(types.size()==_types.size())
6797 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6799 int *retPtr=ret->getPointer();
6800 const int *connI=_nodal_connec_index->getConstPointer();
6801 const int *conn=_nodal_connec->getConstPointer();
6802 int nbOfCells=getNumberOfCells();
6805 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6807 i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6808 int offset=(int)std::distance(connI,i);
6809 const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6810 int nbOfCellsOfCurType=(int)std::distance(i,j);
6811 if(code[3*kk+2]==-1)
6812 for(int k=0;k<nbOfCellsOfCurType;k++)
6816 int idInIdsPerType=code[3*kk+2];
6817 if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6819 const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6822 zePfl->checkAllocated();
6823 if(zePfl->getNumberOfComponents()==1)
6825 for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6827 if(*k>=0 && *k<nbOfCellsOfCurType)
6828 *retPtr=(*k)+offset;
6831 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6832 oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6833 throw INTERP_KERNEL::Exception(oss.str().c_str());
6838 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6841 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6845 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6846 oss << " should be in [0," << idsPerType.size() << ") !";
6847 throw INTERP_KERNEL::Exception(oss.str().c_str());
6856 * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6857 * 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.
6858 * 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.
6859 * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6861 * \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.
6862 * \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,
6863 * \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6864 * \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.
6865 * This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6866 * \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
6868 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6871 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6872 if(profile->getNumberOfComponents()!=1)
6873 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6874 checkConnectivityFullyDefined();
6875 const int *conn=_nodal_connec->getConstPointer();
6876 const int *connI=_nodal_connec_index->getConstPointer();
6877 int nbOfCells=getNumberOfCells();
6878 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6879 std::vector<int> typeRangeVals(1);
6880 for(const int *i=connI;i!=connI+nbOfCells;)
6882 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6883 if(std::find(types.begin(),types.end(),curType)!=types.end())
6885 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6887 types.push_back(curType);
6888 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6889 typeRangeVals.push_back((int)std::distance(connI,i));
6892 DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6893 profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6894 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6895 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6896 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6898 int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6899 code.resize(3*nbOfCastsFinal);
6900 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6901 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6902 for(int i=0;i<nbOfCastsFinal;i++)
6904 int castId=castsPresent->getIJ(i,0);
6905 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6906 idsInPflPerType2.push_back(tmp3);
6907 code[3*i]=(int)types[castId];
6908 code[3*i+1]=tmp3->getNumberOfTuples();
6909 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6910 if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6912 tmp4->copyStringInfoFrom(*profile);
6913 idsPerType2.push_back(tmp4);
6914 code[3*i+2]=(int)idsPerType2.size()-1;
6921 std::size_t sz2=idsInPflPerType2.size();
6922 idsInPflPerType.resize(sz2);
6923 for(std::size_t i=0;i<sz2;i++)
6925 DataArrayInt *locDa=idsInPflPerType2[i];
6927 idsInPflPerType[i]=locDa;
6929 std::size_t sz=idsPerType2.size();
6930 idsPerType.resize(sz);
6931 for(std::size_t i=0;i<sz;i++)
6933 DataArrayInt *locDa=idsPerType2[i];
6935 idsPerType[i]=locDa;
6940 * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6941 * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6942 * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6943 * 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.
6945 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
6947 checkFullyDefined();
6948 nM1LevMesh->checkFullyDefined();
6949 if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6950 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6951 if(_coords!=nM1LevMesh->getCoords())
6952 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6953 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6954 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6955 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6956 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6957 desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6958 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6959 tmp->setConnectivity(tmp0,tmp1);
6960 tmp->renumberCells(ret0->getConstPointer(),false);
6961 revDesc=tmp->getNodalConnectivity();
6962 revDescIndx=tmp->getNodalConnectivityIndex();
6963 DataArrayInt *ret=0;
6964 if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6967 ret->getMaxValue(tmp2);
6969 std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6970 throw INTERP_KERNEL::Exception(oss.str().c_str());
6975 revDescIndx->incrRef();
6978 meshnM1Old2New=ret0;
6983 * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6984 * necessary for writing the mesh to MED file. Additionally returns a permutation array
6985 * in "Old to New" mode.
6986 * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6987 * this array using decrRef() as it is no more needed.
6988 * \throw If the nodal connectivity of cells is not defined.
6990 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
6992 checkConnectivityFullyDefined();
6993 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6994 renumberCells(ret->getConstPointer(),false);
6999 * This methods checks that cells are sorted by their types.
7000 * This method makes asumption (no check) that connectivity is correctly set before calling.
7002 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
7004 checkFullyDefined();
7005 const int *conn=_nodal_connec->getConstPointer();
7006 const int *connI=_nodal_connec_index->getConstPointer();
7007 int nbOfCells=getNumberOfCells();
7008 std::set<INTERP_KERNEL::NormalizedCellType> types;
7009 for(const int *i=connI;i!=connI+nbOfCells;)
7011 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7012 if(types.find(curType)!=types.end())
7014 types.insert(curType);
7015 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7021 * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
7022 * The geometric type order is specified by MED file.
7024 * \sa MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
7026 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
7028 return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7032 * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
7033 * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
7034 * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
7035 * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
7037 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7039 checkFullyDefined();
7040 const int *conn=_nodal_connec->getConstPointer();
7041 const int *connI=_nodal_connec_index->getConstPointer();
7042 int nbOfCells=getNumberOfCells();
7046 std::set<INTERP_KERNEL::NormalizedCellType> sg;
7047 for(const int *i=connI;i!=connI+nbOfCells;)
7049 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7050 const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
7051 if(isTypeExists!=orderEnd)
7053 int pos=(int)std::distance(orderBg,isTypeExists);
7057 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7061 if(sg.find(curType)==sg.end())
7063 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7074 * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
7075 * 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
7076 * 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'.
7078 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
7080 checkConnectivityFullyDefined();
7081 int nbOfCells=getNumberOfCells();
7082 const int *conn=_nodal_connec->getConstPointer();
7083 const int *connI=_nodal_connec_index->getConstPointer();
7084 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
7085 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
7086 tmpa->alloc(nbOfCells,1);
7087 tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
7088 tmpb->fillWithZero();
7089 int *tmp=tmpa->getPointer();
7090 int *tmp2=tmpb->getPointer();
7091 for(const int *i=connI;i!=connI+nbOfCells;i++)
7093 const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
7096 int pos=(int)std::distance(orderBg,where);
7098 tmp[std::distance(connI,i)]=pos;
7102 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
7103 std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
7104 oss << " has a type " << cm.getRepr() << " not in input array of type !";
7105 throw INTERP_KERNEL::Exception(oss.str().c_str());
7108 nbPerType=tmpb.retn();
7113 * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7115 * \return a new object containing the old to new correspondance.
7117 * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7119 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7121 return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7125 * 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.
7126 * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7127 * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7128 * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7130 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7132 DataArrayInt *nbPerType=0;
7133 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7134 nbPerType->decrRef();
7135 return tmpa->buildPermArrPerLevel();
7139 * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7140 * The number of cells remains unchanged after the call of this method.
7141 * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7142 * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7144 * \return the array giving the correspondance old to new.
7146 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7148 checkFullyDefined();
7150 const int *conn=_nodal_connec->getConstPointer();
7151 const int *connI=_nodal_connec_index->getConstPointer();
7152 int nbOfCells=getNumberOfCells();
7153 std::vector<INTERP_KERNEL::NormalizedCellType> types;
7154 for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7155 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7157 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7158 types.push_back(curType);
7159 for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7161 DataArrayInt *ret=DataArrayInt::New();
7162 ret->alloc(nbOfCells,1);
7163 int *retPtr=ret->getPointer();
7164 std::fill(retPtr,retPtr+nbOfCells,-1);
7166 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7168 for(const int *i=connI;i!=connI+nbOfCells;i++)
7169 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7170 retPtr[std::distance(connI,i)]=newCellId++;
7172 renumberCells(retPtr,false);
7177 * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7178 * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7179 * This method makes asumption that connectivity is correctly set before calling.
7181 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7183 checkConnectivityFullyDefined();
7184 const int *conn=_nodal_connec->getConstPointer();
7185 const int *connI=_nodal_connec_index->getConstPointer();
7186 int nbOfCells=getNumberOfCells();
7187 std::vector<MEDCouplingUMesh *> ret;
7188 for(const int *i=connI;i!=connI+nbOfCells;)
7190 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7191 int beginCellId=(int)std::distance(connI,i);
7192 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7193 int endCellId=(int)std::distance(connI,i);
7194 int sz=endCellId-beginCellId;
7195 int *cells=new int[sz];
7196 for(int j=0;j<sz;j++)
7197 cells[j]=beginCellId+j;
7198 MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7206 * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7207 * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7208 * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7210 * \return a newly allocated instance, that the caller must manage.
7211 * \throw If \a this contains more than one geometric type.
7212 * \throw If the nodal connectivity of \a this is not fully defined.
7213 * \throw If the internal data is not coherent.
7215 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7217 checkConnectivityFullyDefined();
7218 if(_types.size()!=1)
7219 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7220 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7221 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7222 ret->setCoords(getCoords());
7223 MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7226 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7227 retC->setNodalConnectivity(c);
7231 MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7233 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7234 DataArrayInt *c=0,*ci=0;
7235 convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7236 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7237 retD->setNodalConnectivity(cs,cis);
7242 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7244 checkConnectivityFullyDefined();
7245 if(_types.size()!=1)
7246 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7247 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7248 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7251 std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7252 oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7253 throw INTERP_KERNEL::Exception(oss.str().c_str());
7255 int nbCells=getNumberOfCells();
7257 int nbNodesPerCell=(int)cm.getNumberOfNodes();
7258 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7259 int *outPtr=connOut->getPointer();
7260 const int *conn=_nodal_connec->begin();
7261 const int *connI=_nodal_connec_index->begin();
7263 for(int i=0;i<nbCells;i++,connI++)
7265 if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7266 outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7269 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 << ") !";
7270 throw INTERP_KERNEL::Exception(oss.str().c_str());
7273 return connOut.retn();
7276 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7278 static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7279 checkConnectivityFullyDefined();
7280 if(_types.size()!=1)
7281 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7282 int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7284 throw INTERP_KERNEL::Exception(msg0);
7285 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7286 c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7287 int *cp(c->getPointer()),*cip(ci->getPointer());
7288 const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7290 for(int i=0;i<nbCells;i++,cip++,incip++)
7292 int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7293 int delta(stop-strt);
7296 if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7297 cp=std::copy(incp+strt,incp+stop,cp);
7299 throw INTERP_KERNEL::Exception(msg0);
7302 throw INTERP_KERNEL::Exception(msg0);
7303 cip[1]=cip[0]+delta;
7305 nodalConn=c.retn(); nodalConnIndex=ci.retn();
7309 * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7310 * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7311 * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7312 * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7313 * are not used here to avoid the build of big permutation array.
7315 * \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
7316 * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7317 * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7318 * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7319 * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7320 * output array gives for each chunck of same type the corresponding mesh id in \b ms.
7321 * \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
7322 * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7324 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7325 DataArrayInt *&szOfCellGrpOfSameType,
7326 DataArrayInt *&idInMsOfCellGrpOfSameType)
7328 std::vector<const MEDCouplingUMesh *> ms2;
7329 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7332 (*it)->checkConnectivityFullyDefined();
7336 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7337 const DataArrayDouble *refCoo=ms2[0]->getCoords();
7338 int meshDim=ms2[0]->getMeshDimension();
7339 std::vector<const MEDCouplingUMesh *> m1ssm;
7340 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7342 std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7343 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7345 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7346 ret1->alloc(0,1); ret2->alloc(0,1);
7347 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7349 if(meshDim!=(*it)->getMeshDimension())
7350 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7351 if(refCoo!=(*it)->getCoords())
7352 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7353 std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7354 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7355 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7356 for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7358 MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7359 m1ssmSingleAuto.push_back(singleCell);
7360 m1ssmSingle.push_back(singleCell);
7361 ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7364 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7365 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7366 std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7367 for(std::size_t i=0;i<m1ssm.size();i++)
7368 m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7369 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7370 szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7371 idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7376 * This method returns a newly created DataArrayInt instance.
7377 * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7379 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7381 checkFullyDefined();
7382 const int *conn=_nodal_connec->getConstPointer();
7383 const int *connIndex=_nodal_connec_index->getConstPointer();
7384 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7385 for(const int *w=begin;w!=end;w++)
7386 if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7387 ret->pushBackSilent(*w);
7392 * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7393 * are in [0:getNumberOfCells())
7395 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7397 checkFullyDefined();
7398 const int *conn=_nodal_connec->getConstPointer();
7399 const int *connI=_nodal_connec_index->getConstPointer();
7400 int nbOfCells=getNumberOfCells();
7401 std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7402 int *tmp=new int[nbOfCells];
7403 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7406 for(const int *i=connI;i!=connI+nbOfCells;i++)
7407 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7408 tmp[std::distance(connI,i)]=j++;
7410 DataArrayInt *ret=DataArrayInt::New();
7411 ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7412 ret->copyStringInfoFrom(*da);
7413 int *retPtr=ret->getPointer();
7414 const int *daPtr=da->getConstPointer();
7415 int nbOfElems=da->getNbOfElems();
7416 for(int k=0;k<nbOfElems;k++)
7417 retPtr[k]=tmp[daPtr[k]];
7423 * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7424 * This method \b works \b for mesh sorted by type.
7425 * cells whose ids is in 'idsPerGeoType' array.
7426 * This method conserves coords and name of mesh.
7428 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7430 std::vector<int> code=getDistributionOfTypes();
7431 std::size_t nOfTypesInThis=code.size()/3;
7432 int sz=0,szOfType=0;
7433 for(std::size_t i=0;i<nOfTypesInThis;i++)
7438 szOfType=code[3*i+1];
7440 for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7441 if(*work<0 || *work>=szOfType)
7443 std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7444 oss << ". It should be in [0," << szOfType << ") !";
7445 throw INTERP_KERNEL::Exception(oss.str().c_str());
7447 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7448 int *idsPtr=idsTokeep->getPointer();
7450 for(std::size_t i=0;i<nOfTypesInThis;i++)
7453 for(int j=0;j<code[3*i+1];j++)
7456 idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7457 offset+=code[3*i+1];
7459 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7460 ret->copyTinyInfoFrom(this);
7465 * This method returns a vector of size 'this->getNumberOfCells()'.
7466 * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7468 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7470 int ncell=getNumberOfCells();
7471 std::vector<bool> ret(ncell);
7472 const int *cI=getNodalConnectivityIndex()->getConstPointer();
7473 const int *c=getNodalConnectivity()->getConstPointer();
7474 for(int i=0;i<ncell;i++)
7476 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7477 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7478 ret[i]=cm.isQuadratic();
7484 * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7486 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7488 if(other->getType()!=UNSTRUCTURED)
7489 throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7490 const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7491 return MergeUMeshes(this,otherC);
7495 * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7496 * computed by averaging coordinates of cell nodes, so this method is not a right
7497 * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7498 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7499 * this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7500 * components. The caller is to delete this array using decrRef() as it is
7502 * \throw If the coordinates array is not set.
7503 * \throw If the nodal connectivity of cells is not defined.
7504 * \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7506 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7508 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7509 int spaceDim=getSpaceDimension();
7510 int nbOfCells=getNumberOfCells();
7511 ret->alloc(nbOfCells,spaceDim);
7512 ret->copyStringInfoFrom(*getCoords());
7513 double *ptToFill=ret->getPointer();
7514 const int *nodal=_nodal_connec->getConstPointer();
7515 const int *nodalI=_nodal_connec_index->getConstPointer();
7516 const double *coor=_coords->getConstPointer();
7517 for(int i=0;i<nbOfCells;i++)
7519 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7520 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7527 * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7528 * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the
7530 * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned
7531 * DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7533 * \sa MEDCouplingUMesh::getBarycenterAndOwner
7534 * \throw If \a this is not fully defined (coordinates and connectivity)
7535 * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7537 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7539 checkFullyDefined();
7540 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7541 int spaceDim=getSpaceDimension();
7542 int nbOfCells=getNumberOfCells();
7543 int nbOfNodes=getNumberOfNodes();
7544 ret->alloc(nbOfCells,spaceDim);
7545 double *ptToFill=ret->getPointer();
7546 const int *nodal=_nodal_connec->getConstPointer();
7547 const int *nodalI=_nodal_connec_index->getConstPointer();
7548 const double *coor=_coords->getConstPointer();
7549 for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7551 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7552 std::fill(ptToFill,ptToFill+spaceDim,0.);
7553 if(type!=INTERP_KERNEL::NORM_POLYHED)
7555 for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7557 if(*conn>=0 && *conn<nbOfNodes)
7558 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7561 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," << nbOfNodes << ") !";
7562 throw INTERP_KERNEL::Exception(oss.str().c_str());
7565 int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7566 if(nbOfNodesInCell>0)
7567 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7570 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7571 throw INTERP_KERNEL::Exception(oss.str().c_str());
7576 std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7578 for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7580 if(*it>=0 && *it<nbOfNodes)
7581 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7584 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," << nbOfNodes << ") !";
7585 throw INTERP_KERNEL::Exception(oss.str().c_str());
7589 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7592 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7593 throw INTERP_KERNEL::Exception(oss.str().c_str());
7601 * Returns a new DataArrayDouble holding barycenters of specified cells. The
7602 * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7603 * are specified via an array of cell ids.
7604 * \warning Validity of the specified cell ids is not checked!
7605 * Valid range is [ 0, \a this->getNumberOfCells() ).
7606 * \param [in] begin - an array of cell ids of interest.
7607 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7608 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7609 * end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7610 * caller is to delete this array using decrRef() as it is no more needed.
7611 * \throw If the coordinates array is not set.
7612 * \throw If the nodal connectivity of cells is not defined.
7614 * \if ENABLE_EXAMPLES
7615 * \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7616 * \ref py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7619 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7621 DataArrayDouble *ret=DataArrayDouble::New();
7622 int spaceDim=getSpaceDimension();
7623 int nbOfTuple=(int)std::distance(begin,end);
7624 ret->alloc(nbOfTuple,spaceDim);
7625 double *ptToFill=ret->getPointer();
7626 double *tmp=new double[spaceDim];
7627 const int *nodal=_nodal_connec->getConstPointer();
7628 const int *nodalI=_nodal_connec_index->getConstPointer();
7629 const double *coor=_coords->getConstPointer();
7630 for(const int *w=begin;w!=end;w++)
7632 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7633 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7641 * 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".
7642 * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7643 * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7644 * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7645 * This method is useful to detect 2D cells in 3D space that are not coplanar.
7647 * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7648 * \throw If spaceDim!=3 or meshDim!=2.
7649 * \throw If connectivity of \a this is invalid.
7650 * \throw If connectivity of a cell in \a this points to an invalid node.
7652 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7654 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7655 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7656 if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7657 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7658 ret->alloc(nbOfCells,4);
7659 double *retPtr(ret->getPointer());
7660 const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7661 const double *coor(_coords->begin());
7662 for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7664 double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7665 if(nodalI[1]-nodalI[0]>=3)
7667 for(int j=0;j<3;j++)
7669 int nodeId(nodal[nodalI[0]+1+j]);
7670 if(nodeId>=0 && nodeId<nbOfNodes)
7671 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7674 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7675 throw INTERP_KERNEL::Exception(oss.str().c_str());
7681 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7682 throw INTERP_KERNEL::Exception(oss.str().c_str());
7684 INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7685 retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7691 * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7694 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7697 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7698 da->checkAllocated();
7699 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7701 int nbOfTuples=da->getNumberOfTuples();
7702 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7703 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7704 c->alloc(2*nbOfTuples,1);
7705 cI->alloc(nbOfTuples+1,1);
7706 int *cp=c->getPointer();
7707 int *cip=cI->getPointer();
7709 for(int i=0;i<nbOfTuples;i++)
7711 *cp++=INTERP_KERNEL::NORM_POINT1;
7715 ret->setConnectivity(c,cI,true);
7719 * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7720 * Cells and nodes of
7721 * the first mesh precede cells and nodes of the second mesh within the result mesh.
7722 * \param [in] mesh1 - the first mesh.
7723 * \param [in] mesh2 - the second mesh.
7724 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7725 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7726 * is no more needed.
7727 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7728 * \throw If the coordinates array is not set in none of the meshes.
7729 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7730 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7732 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7734 std::vector<const MEDCouplingUMesh *> tmp(2);
7735 tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7736 return MergeUMeshes(tmp);
7740 * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7741 * Cells and nodes of
7742 * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7743 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7744 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7745 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7746 * is no more needed.
7747 * \throw If \a a.size() == 0.
7748 * \throw If \a a[ *i* ] == NULL.
7749 * \throw If the coordinates array is not set in none of the meshes.
7750 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7751 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7753 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7755 std::size_t sz=a.size();
7757 return MergeUMeshesLL(a);
7758 for(std::size_t ii=0;ii<sz;ii++)
7761 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7762 throw INTERP_KERNEL::Exception(oss.str().c_str());
7764 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7765 std::vector< const MEDCouplingUMesh * > aa(sz);
7767 for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7769 const MEDCouplingUMesh *cur=a[i];
7770 const DataArrayDouble *coo=cur->getCoords();
7772 spaceDim=coo->getNumberOfComponents();
7775 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7776 for(std::size_t i=0;i<sz;i++)
7778 bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7781 return MergeUMeshesLL(aa);
7786 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7789 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7790 std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7791 int meshDim=(*it)->getMeshDimension();
7792 int nbOfCells=(*it)->getNumberOfCells();
7793 int meshLgth=(*it++)->getMeshLength();
7794 for(;it!=a.end();it++)
7796 if(meshDim!=(*it)->getMeshDimension())
7797 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7798 nbOfCells+=(*it)->getNumberOfCells();
7799 meshLgth+=(*it)->getMeshLength();
7801 std::vector<const MEDCouplingPointSet *> aps(a.size());
7802 std::copy(a.begin(),a.end(),aps.begin());
7803 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7804 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7805 ret->setCoords(pts);
7806 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7807 c->alloc(meshLgth,1);
7808 int *cPtr=c->getPointer();
7809 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7810 cI->alloc(nbOfCells+1,1);
7811 int *cIPtr=cI->getPointer();
7815 for(it=a.begin();it!=a.end();it++)
7817 int curNbOfCell=(*it)->getNumberOfCells();
7818 const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7819 const int *curC=(*it)->_nodal_connec->getConstPointer();
7820 cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7821 for(int j=0;j<curNbOfCell;j++)
7823 const int *src=curC+curCI[j];
7825 for(;src!=curC+curCI[j+1];src++,cPtr++)
7833 offset+=curCI[curNbOfCell];
7834 offset2+=(*it)->getNumberOfNodes();
7837 ret->setConnectivity(c,cI,true);
7844 * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7845 * dimension and sharing the node coordinates array.
7846 * All cells of the first mesh precede all cells of the second mesh
7847 * within the result mesh.
7848 * \param [in] mesh1 - the first mesh.
7849 * \param [in] mesh2 - the second mesh.
7850 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7851 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7852 * is no more needed.
7853 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7854 * \throw If the meshes do not share the node coordinates array.
7855 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7856 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7858 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7860 std::vector<const MEDCouplingUMesh *> tmp(2);
7861 tmp[0]=mesh1; tmp[1]=mesh2;
7862 return MergeUMeshesOnSameCoords(tmp);
7866 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7867 * dimension and sharing the node coordinates array.
7868 * All cells of the *i*-th mesh precede all cells of the
7869 * (*i*+1)-th mesh within the result mesh.
7870 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7871 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7872 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7873 * is no more needed.
7874 * \throw If \a a.size() == 0.
7875 * \throw If \a a[ *i* ] == NULL.
7876 * \throw If the meshes do not share the node coordinates array.
7877 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7878 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7880 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7883 throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7884 for(std::size_t ii=0;ii<meshes.size();ii++)
7887 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7888 throw INTERP_KERNEL::Exception(oss.str().c_str());
7890 const DataArrayDouble *coords=meshes.front()->getCoords();
7891 int meshDim=meshes.front()->getMeshDimension();
7892 std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7894 int meshIndexLgth=0;
7895 for(;iter!=meshes.end();iter++)
7897 if(coords!=(*iter)->getCoords())
7898 throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7899 if(meshDim!=(*iter)->getMeshDimension())
7900 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7901 meshLgth+=(*iter)->getMeshLength();
7902 meshIndexLgth+=(*iter)->getNumberOfCells();
7904 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7905 nodal->alloc(meshLgth,1);
7906 int *nodalPtr=nodal->getPointer();
7907 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7908 nodalIndex->alloc(meshIndexLgth+1,1);
7909 int *nodalIndexPtr=nodalIndex->getPointer();
7911 for(iter=meshes.begin();iter!=meshes.end();iter++)
7913 const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7914 const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7915 int nbOfCells=(*iter)->getNumberOfCells();
7916 int meshLgth2=(*iter)->getMeshLength();
7917 nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7918 if(iter!=meshes.begin())
7919 nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7921 nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7924 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7925 ret->setName("merge");
7926 ret->setMeshDimension(meshDim);
7927 ret->setConnectivity(nodal,nodalIndex,true);
7928 ret->setCoords(coords);
7933 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7934 * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7935 * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7936 * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7937 * New" mode are returned for each input mesh.
7938 * \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7939 * \param [in] compType - specifies a cell comparison technique. For meaning of its
7940 * valid values [0,1,2], see zipConnectivityTraducer().
7941 * \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7942 * meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7943 * mesh. The caller is to delete each of the arrays using decrRef() as it is
7945 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7946 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7947 * is no more needed.
7948 * \throw If \a meshes.size() == 0.
7949 * \throw If \a meshes[ *i* ] == NULL.
7950 * \throw If the meshes do not share the node coordinates array.
7951 * \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7952 * \throw If the \a meshes are of different dimension (getMeshDimension()).
7953 * \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7954 * \throw If the nodal connectivity any of \a meshes includes an invalid id.
7956 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7958 //All checks are delegated to MergeUMeshesOnSameCoords
7959 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7960 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7961 corr.resize(meshes.size());
7962 std::size_t nbOfMeshes=meshes.size();
7964 const int *o2nPtr=o2n->getConstPointer();
7965 for(std::size_t i=0;i<nbOfMeshes;i++)
7967 DataArrayInt *tmp=DataArrayInt::New();
7968 int curNbOfCells=meshes[i]->getNumberOfCells();
7969 tmp->alloc(curNbOfCells,1);
7970 std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7971 offset+=curNbOfCells;
7972 tmp->setName(meshes[i]->getName());
7979 * Makes all given meshes share the nodal connectivity array. The common connectivity
7980 * array is created by concatenating the connectivity arrays of all given meshes. All
7981 * the given meshes must be of the same space dimension but dimension of cells **can
7982 * differ**. This method is particulary useful in MEDLoader context to build a \ref
7983 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7984 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7985 * \param [in,out] meshes - a vector of meshes to update.
7986 * \throw If any of \a meshes is NULL.
7987 * \throw If the coordinates array is not set in any of \a meshes.
7988 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7989 * \throw If \a meshes are of different space dimension.
7991 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
7993 std::size_t sz=meshes.size();
7996 std::vector< const DataArrayDouble * > coords(meshes.size());
7997 std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7998 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
8002 (*it)->checkConnectivityFullyDefined();
8003 const DataArrayDouble *coo=(*it)->getCoords();
8008 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8009 oss << " has no coordinate array defined !";
8010 throw INTERP_KERNEL::Exception(oss.str().c_str());
8015 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8016 oss << " is null !";
8017 throw INTERP_KERNEL::Exception(oss.str().c_str());
8020 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
8021 std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
8022 int offset=(*it)->getNumberOfNodes();
8023 (*it++)->setCoords(res);
8024 for(;it!=meshes.end();it++)
8026 int oldNumberOfNodes=(*it)->getNumberOfNodes();
8027 (*it)->setCoords(res);
8028 (*it)->shiftNodeNumbersInConn(offset);
8029 offset+=oldNumberOfNodes;
8034 * Merges nodes coincident with a given precision within all given meshes that share
8035 * the nodal connectivity array. The given meshes **can be of different** mesh
8036 * dimension. This method is particulary useful in MEDLoader context to build a \ref
8037 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8038 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8039 * \param [in,out] meshes - a vector of meshes to update.
8040 * \param [in] eps - the precision used to detect coincident nodes (infinite norm).
8041 * \throw If any of \a meshes is NULL.
8042 * \throw If the \a meshes do not share the same node coordinates array.
8043 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8045 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
8049 std::set<const DataArrayDouble *> s;
8050 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8053 s.insert((*it)->getCoords());
8056 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 !";
8057 throw INTERP_KERNEL::Exception(oss.str().c_str());
8062 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 !";
8063 throw INTERP_KERNEL::Exception(oss.str().c_str());
8065 const DataArrayDouble *coo=*(s.begin());
8069 DataArrayInt *comm,*commI;
8070 coo->findCommonTuples(eps,-1,comm,commI);
8071 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
8072 int oldNbOfNodes=coo->getNumberOfTuples();
8074 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
8075 if(oldNbOfNodes==newNbOfNodes)
8077 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
8078 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8080 (*it)->renumberNodesInConn(o2n->getConstPointer());
8081 (*it)->setCoords(newCoords);
8086 * 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.
8087 * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
8088 * \param isQuad specifies the policy of connectivity.
8089 * @ret in/out parameter in which the result will be append
8091 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
8093 INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
8094 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
8095 ret.push_back(cm.getExtrudedType());
8096 int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
8099 case INTERP_KERNEL::NORM_POINT1:
8101 ret.push_back(connBg[1]);
8102 ret.push_back(connBg[1]+nbOfNodesPerLev);
8105 case INTERP_KERNEL::NORM_SEG2:
8107 int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
8108 ret.insert(ret.end(),conn,conn+4);
8111 case INTERP_KERNEL::NORM_SEG3:
8113 int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8114 ret.insert(ret.end(),conn,conn+8);
8117 case INTERP_KERNEL::NORM_QUAD4:
8119 int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8120 ret.insert(ret.end(),conn,conn+8);
8123 case INTERP_KERNEL::NORM_TRI3:
8125 int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8126 ret.insert(ret.end(),conn,conn+6);
8129 case INTERP_KERNEL::NORM_TRI6:
8131 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,
8132 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8133 ret.insert(ret.end(),conn,conn+15);
8136 case INTERP_KERNEL::NORM_QUAD8:
8139 connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8140 connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8141 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8143 ret.insert(ret.end(),conn,conn+20);
8146 case INTERP_KERNEL::NORM_POLYGON:
8148 std::back_insert_iterator< std::vector<int> > ii(ret);
8149 std::copy(connBg+1,connEnd,ii);
8151 std::reverse_iterator<const int *> rConnBg(connEnd);
8152 std::reverse_iterator<const int *> rConnEnd(connBg+1);
8153 std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8154 std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8155 for(std::size_t i=0;i<nbOfRadFaces;i++)
8158 int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8159 std::copy(conn,conn+4,ii);
8164 throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8169 * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8171 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8174 double v[3]={0.,0.,0.};
8175 std::size_t sz=std::distance(begin,end);
8180 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];
8181 v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8182 v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8184 double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8186 // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8187 // SEG3 forming a circle):
8188 if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8190 v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8191 for(std::size_t j=0;j<sz;j++)
8193 if (j%2) // current point i is quadratic, next point i+1 is standard
8196 ip1 = (j+1)%sz; // ip1 = "i+1"
8198 else // current point i is standard, next point i+1 is quadratic
8203 v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8204 v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8205 v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8207 ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8213 * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8215 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8217 std::vector<std::pair<int,int> > edges;
8218 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8219 const int *bgFace=begin;
8220 for(std::size_t i=0;i<nbOfFaces;i++)
8222 const int *endFace=std::find(bgFace+1,end,-1);
8223 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8224 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8226 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8227 if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8229 edges.push_back(p1);
8233 return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8237 * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8239 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8241 double vec0[3],vec1[3];
8242 std::size_t sz=std::distance(begin,end);
8244 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8245 int nbOfNodes=(int)sz/2;
8246 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8247 const double *pt0=coords+3*begin[0];
8248 const double *pt1=coords+3*begin[nbOfNodes];
8249 vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8250 return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8253 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8255 std::size_t sz=std::distance(begin,end);
8256 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8257 std::size_t nbOfNodes(sz/2);
8258 std::copy(begin,end,(int *)tmp);
8259 for(std::size_t j=1;j<nbOfNodes;j++)
8261 begin[j]=tmp[nbOfNodes-j];
8262 begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8266 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8268 std::size_t sz=std::distance(begin,end);
8270 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8271 double vec0[3],vec1[3];
8272 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8273 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];
8274 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;
8277 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8279 std::size_t sz=std::distance(begin,end);
8281 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8283 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8284 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8285 return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8289 * 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 )
8290 * 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
8293 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8294 * \param [in] coords the coordinates with nb of components exactly equal to 3
8295 * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8296 * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8297 * \param [out] res the result is put at the end of the vector without any alteration of the data.
8299 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8301 int nbFaces=std::count(begin+1,end,-1)+1;
8302 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8303 double *vPtr=v->getPointer();
8304 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8305 double *pPtr=p->getPointer();
8306 const int *stFaceConn=begin+1;
8307 for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8309 const int *endFaceConn=std::find(stFaceConn,end,-1);
8310 ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8311 stFaceConn=endFaceConn+1;
8313 pPtr=p->getPointer(); vPtr=v->getPointer();
8314 DataArrayInt *comm1=0,*commI1=0;
8315 v->findCommonTuples(eps,-1,comm1,commI1);
8316 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8317 const int *comm1Ptr=comm1->getConstPointer();
8318 const int *commI1Ptr=commI1->getConstPointer();
8319 int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8320 res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8322 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8323 mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8324 mm->finishInsertingCells();
8326 for(int i=0;i<nbOfGrps1;i++)
8328 int vecId=comm1Ptr[commI1Ptr[i]];
8329 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8330 DataArrayInt *comm2=0,*commI2=0;
8331 tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8332 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8333 const int *comm2Ptr=comm2->getConstPointer();
8334 const int *commI2Ptr=commI2->getConstPointer();
8335 int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8336 for(int j=0;j<nbOfGrps2;j++)
8338 if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8340 res->insertAtTheEnd(begin,end);
8341 res->pushBackSilent(-1);
8345 int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8346 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8347 ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8348 DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8349 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8350 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8351 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8352 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8353 const int *idsNodePtr=idsNode->getConstPointer();
8354 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];
8355 double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8356 double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8357 if(std::abs(norm)>eps)
8359 double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8360 mm3->rotate(center,vec,angle);
8362 mm3->changeSpaceDimension(2);
8363 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8364 const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8365 const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8366 int nbOfCells=mm4->getNumberOfCells();
8367 for(int k=0;k<nbOfCells;k++)
8370 for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8371 res->pushBackSilent(idsNodePtr[*work]);
8372 res->pushBackSilent(-1);
8377 res->popBackSilent();
8381 * 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
8382 * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8384 * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8385 * \param [in] coords coordinates expected to have 3 components.
8386 * \param [in] begin start of the nodal connectivity of the face.
8387 * \param [in] end end of the nodal connectivity (excluded) of the face.
8388 * \param [out] v the normalized vector of size 3
8389 * \param [out] p the pos of plane
8391 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8393 std::size_t nbPoints=std::distance(begin,end);
8395 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8396 double vec[3]={0.,0.,0.};
8398 bool refFound=false;
8399 for(;j<nbPoints-1 && !refFound;j++)
8401 vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8402 vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8403 vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8404 double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8408 vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8411 for(std::size_t i=j;i<nbPoints-1;i++)
8414 curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8415 curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8416 curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8417 double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8420 curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8421 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];
8422 norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8425 v[0]/=norm; v[1]/=norm; v[2]/=norm;
8426 *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8430 throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8434 * This method tries to obtain a well oriented polyhedron.
8435 * If the algorithm fails, an exception will be thrown.
8437 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8439 std::list< std::pair<int,int> > edgesOK,edgesFinished;
8440 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8441 std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8443 int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8444 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8445 for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8447 while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8450 std::size_t smthChanged=0;
8451 for(std::size_t i=0;i<nbOfFaces;i++)
8453 endFace=std::find(bgFace+1,end,-1);
8454 nbOfEdgesInFace=std::distance(bgFace,endFace);
8458 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8460 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8461 std::pair<int,int> p2(p1.second,p1.first);
8462 bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8463 bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8464 if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8469 std::reverse(bgFace+1,endFace);
8470 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8472 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8473 std::pair<int,int> p2(p1.second,p1.first);
8474 if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8475 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8476 if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8477 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8478 std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8479 if(it!=edgesOK.end())
8482 edgesFinished.push_back(p1);
8485 edgesOK.push_back(p1);
8492 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8494 if(!edgesOK.empty())
8495 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8496 if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8497 {//not lucky ! The first face was not correctly oriented : reorient all faces...
8499 for(std::size_t i=0;i<nbOfFaces;i++)
8501 endFace=std::find(bgFace+1,end,-1);
8502 std::reverse(bgFace+1,endFace);
8508 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8510 int nbOfNodesExpected(skin->getNumberOfNodes());
8511 const int *n2oPtr(n2o->getConstPointer());
8512 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8513 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8514 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8515 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8516 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8517 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8518 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_POLYGON;
8519 if(nbOfNodesExpected<1)
8521 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8522 *work++=n2oPtr[prevNode];
8523 for(int i=1;i<nbOfNodesExpected;i++)
8525 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8527 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8528 conn.erase(prevNode);
8531 int curNode(*(conn.begin()));
8532 *work++=n2oPtr[curNode];
8533 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8534 shar.erase(prevCell);
8537 prevCell=*(shar.begin());
8541 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8544 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8547 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8552 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8554 int nbOfNodesExpected(skin->getNumberOfNodes());
8555 int nbOfTurn(nbOfNodesExpected/2);
8556 const int *n2oPtr(n2o->getConstPointer());
8557 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8558 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8559 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8560 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8561 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8562 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8563 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_QPOLYG;
8564 if(nbOfNodesExpected<1)
8566 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8567 *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8568 for(int i=1;i<nbOfTurn;i++)
8570 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8572 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8573 conn.erase(prevNode);
8576 int curNode(*(conn.begin()));
8577 *work=n2oPtr[curNode];
8578 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8579 shar.erase(prevCell);
8582 int curCell(*(shar.begin()));
8583 work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8589 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8592 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8595 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8601 * This method makes the assumption spacedimension == meshdimension == 2.
8602 * This method works only for linear cells.
8604 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8606 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8608 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8609 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8610 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8611 int oldNbOfNodes(skin->getNumberOfNodes());
8612 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8613 int nbOfNodesExpected(skin->getNumberOfNodes());
8614 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8615 int nbCells(skin->getNumberOfCells());
8616 if(nbCells==nbOfNodesExpected)
8617 return buildUnionOf2DMeshLinear(skin,n2o);
8618 else if(2*nbCells==nbOfNodesExpected)
8619 return buildUnionOf2DMeshQuadratic(skin,n2o);
8621 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8625 * This method makes the assumption spacedimension == meshdimension == 3.
8626 * This method works only for linear cells.
8628 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8630 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8632 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8633 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8634 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8635 const int *conn=m->getNodalConnectivity()->getConstPointer();
8636 const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8637 int nbOfCells=m->getNumberOfCells();
8638 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8639 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED;
8642 work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8643 for(int i=1;i<nbOfCells;i++)
8646 work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8652 * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8653 * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8655 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8659 for(int i=0;i<nbOfNodesInCell;i++)
8660 w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8661 else if(spaceDim==2)
8663 for(int i=0;i<nbOfNodesInCell;i++)
8665 w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8670 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8673 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8675 int nbOfCells=getNumberOfCells();
8677 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8678 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};
8679 ofs << " <" << getVTKDataSetType() << ">\n";
8680 ofs << " <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8681 ofs << " <PointData>\n" << pointData << std::endl;
8682 ofs << " </PointData>\n";
8683 ofs << " <CellData>\n" << cellData << std::endl;
8684 ofs << " </CellData>\n";
8685 ofs << " <Points>\n";
8686 if(getSpaceDimension()==3)
8687 _coords->writeVTK(ofs,8,"Points",byteData);
8690 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8691 coo->writeVTK(ofs,8,"Points",byteData);
8693 ofs << " </Points>\n";
8694 ofs << " <Cells>\n";
8695 const int *cPtr=_nodal_connec->getConstPointer();
8696 const int *cIPtr=_nodal_connec_index->getConstPointer();
8697 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8698 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8699 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8700 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8701 int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8702 int szFaceOffsets=0,szConn=0;
8703 for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8706 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8709 *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8710 w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8714 int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8715 *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8716 std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8717 *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8718 w4=std::copy(c.begin(),c.end(),w4);
8721 types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8722 types->writeVTK(ofs,8,"UInt8","types",byteData);
8723 offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8724 if(szFaceOffsets!=0)
8725 {//presence of Polyhedra
8726 connectivity->reAlloc(szConn);
8727 faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8728 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8729 w1=faces->getPointer();
8730 for(int i=0;i<nbOfCells;i++)
8731 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8733 int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8735 const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8736 for(int j=0;j<nbFaces;j++)
8738 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8739 *w1++=(int)std::distance(w6,w5);
8740 w1=std::copy(w6,w5,w1);
8744 faces->writeVTK(ofs,8,"Int32","faces",byteData);
8746 connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8747 ofs << " </Cells>\n";
8748 ofs << " </Piece>\n";
8749 ofs << " </" << getVTKDataSetType() << ">\n";
8752 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8754 stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8756 { stream << " Not set !"; return ; }
8757 stream << " Mesh dimension : " << _mesh_dim << ".";
8761 { stream << " No coordinates set !"; return ; }
8762 if(!_coords->isAllocated())
8763 { stream << " Coordinates set but not allocated !"; return ; }
8764 stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8765 stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8766 if(!_nodal_connec_index)
8767 { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8768 if(!_nodal_connec_index->isAllocated())
8769 { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8770 int lgth=_nodal_connec_index->getNumberOfTuples();
8771 int cpt=_nodal_connec_index->getNumberOfComponents();
8772 if(cpt!=1 || lgth<1)
8774 stream << std::endl << "Number of cells : " << lgth-1 << ".";
8777 std::string MEDCouplingUMesh::getVTKDataSetType() const
8779 return std::string("UnstructuredGrid");
8782 std::string MEDCouplingUMesh::getVTKFileExtension() const
8784 return std::string("vtu");
8788 * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8789 * returns a result mesh constituted by polygons.
8790 * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8791 * all nodes from m2.
8792 * The meshes should be in 2D space. In
8793 * addition, returns two arrays mapping cells of the result mesh to cells of the input
8795 * \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
8796 * 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)
8797 * \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
8798 * 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)
8799 * \param [in] eps - precision used to detect coincident mesh entities.
8800 * \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8801 * cell an id of the cell of \a m1 it comes from. The caller is to delete
8802 * this array using decrRef() as it is no more needed.
8803 * \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8804 * cell an id of the cell of \a m2 it comes from. -1 value means that a
8805 * result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8806 * any cell of \a m2. The caller is to delete this array using decrRef() as
8807 * it is no more needed.
8808 * \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8809 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8810 * is no more needed.
8811 * \throw If the coordinates array is not set in any of the meshes.
8812 * \throw If the nodal connectivity of cells is not defined in any of the meshes.
8813 * \throw If any of the meshes is not a 2D mesh in 2D space.
8815 * \sa conformize2D, mergeNodes
8817 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8818 double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8821 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
8822 m1->checkFullyDefined();
8823 m2->checkFullyDefined();
8824 if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8825 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!");
8827 // Step 1: compute all edge intersections (new nodes)
8828 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8829 MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
8830 DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8831 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
8832 IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
8833 m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8834 addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
8835 revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8836 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8837 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8839 // Step 2: re-order newly created nodes according to the ordering found in m2
8840 std::vector< std::vector<int> > intersectEdge2;
8841 BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8842 subDiv2.clear(); dd5=0; dd6=0;
8845 std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8846 std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8847 BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8848 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8850 // Step 4: Prepare final result:
8851 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
8852 addCooDa->alloc((int)(addCoo.size())/2,2);
8853 std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8854 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
8855 addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8856 std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8857 std::vector<const DataArrayDouble *> coordss(4);
8858 coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8859 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
8860 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
8861 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8862 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8863 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8864 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8865 ret->setConnectivity(conn,connI,true);
8866 ret->setCoords(coo);
8867 cellNb1=c1.retn(); cellNb2=c2.retn();
8873 bool IsColinearOfACellOf(const std::vector< std::vector<int> >& intersectEdge1, const std::vector<int>& candidates, int start, int stop, int& retVal)
8875 if(candidates.empty())
8877 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
8879 const std::vector<int>& pool(intersectEdge1[*it]);
8880 int tmp[2]; tmp[0]=start; tmp[1]=stop;
8881 if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
8886 tmp[0]=stop; tmp[1]=start;
8887 if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
8896 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,
8897 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInRetColinear, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInMesh1DForIdsInRetColinear)
8899 idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1);
8900 idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1);
8901 int nCells(mesh1D->getNumberOfCells());
8902 if(nCells!=(int)intersectEdge2.size())
8903 throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
8904 const DataArrayDouble *coo2(mesh1D->getCoords());
8905 const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
8906 const double *coo2Ptr(coo2->begin());
8907 int offset1(coords1->getNumberOfTuples());
8908 int offset2(offset1+coo2->getNumberOfTuples());
8909 int offset3(offset2+addCoo.size()/2);
8910 std::vector<double> addCooQuad;
8911 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
8912 int tmp[4],cicnt(0),kk(0);
8913 for(int i=0;i<nCells;i++)
8915 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
8916 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
8917 const std::vector<int>& subEdges(intersectEdge2[i]);
8918 int nbSubEdge(subEdges.size()/2);
8919 for(int j=0;j<nbSubEdge;j++,kk++)
8921 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));
8922 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
8923 INTERP_KERNEL::Edge *e2Ptr(e2);
8924 std::map<int,int>::const_iterator itm;
8925 if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
8927 tmp[0]=INTERP_KERNEL::NORM_SEG3;
8928 itm=mergedNodes.find(subEdges[2*j]);
8929 tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
8930 itm=mergedNodes.find(subEdges[2*j+1]);
8931 tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
8932 tmp[3]=offset3+(int)addCooQuad.size()/2;
8934 e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2);
8936 cOut->insertAtTheEnd(tmp,tmp+4);
8937 ciOut->pushBackSilent(cicnt);
8941 tmp[0]=INTERP_KERNEL::NORM_SEG2;
8942 itm=mergedNodes.find(subEdges[2*j]);
8943 tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
8944 itm=mergedNodes.find(subEdges[2*j+1]);
8945 tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
8947 cOut->insertAtTheEnd(tmp,tmp+3);
8948 ciOut->pushBackSilent(cicnt);
8951 if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00))
8953 idsInRetColinear->pushBackSilent(kk);
8954 idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00);
8959 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
8960 ret->setConnectivity(cOut,ciOut,true);
8961 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr3(DataArrayDouble::New());
8962 arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
8963 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
8964 std::vector<const DataArrayDouble *> coordss(4);
8965 coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
8966 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
8967 ret->setCoords(arr);
8971 MEDCouplingUMesh *BuildRefined2DCellLinear(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
8973 std::vector<int> allEdges;
8974 for(const int *it2(descBg);it2!=descEnd;it2++)
8976 const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
8978 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
8980 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
8982 std::size_t nb(allEdges.size());
8984 throw INTERP_KERNEL::Exception("BuildRefined2DCellLinear : internal error 1 !");
8985 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
8986 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
8987 ret->setCoords(coords);
8988 ret->allocateCells(1);
8989 std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
8990 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
8991 connOut[kk]=allEdges[2*kk];
8992 ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]);
8996 MEDCouplingUMesh *BuildRefined2DCellQuadratic(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
8998 const int *c(mesh2D->getNodalConnectivity()->begin()),*ci(mesh2D->getNodalConnectivityIndex()->begin());
8999 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[cellIdInMesh2D]]));
9001 unsigned sz(cm.getNumberOfSons2(c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1));
9002 if(sz!=std::distance(descBg,descEnd))
9003 throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 1 !");
9004 INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]]);
9005 std::vector<int> allEdges,centers;
9006 const double *coordsPtr(coords->begin());
9007 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
9008 int offset(coords->getNumberOfTuples());
9009 for(const int *it2(descBg);it2!=descEnd;it2++,ii++)
9011 INTERP_KERNEL::NormalizedCellType typeOfSon;
9012 cm.fillSonCellNodalConnectivity2(ii,c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1,tmpPtr,typeOfSon);
9013 const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9015 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9017 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9019 centers.push_back(tmpPtr[2]);//special case where no subsplit of edge -> reuse the original center.
9021 {//the current edge has been subsplit -> create corresponding centers.
9022 std::size_t nbOfCentersToAppend(edge1.size()/2);
9023 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9024 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpPtr,coordsPtr,m));
9025 std::vector<int>::const_iterator it3(allEdges.end()-edge1.size());
9026 for(std::size_t k=0;k<nbOfCentersToAppend;k++)
9029 const double *aa(coordsPtr+2*(*it3++));
9030 const double *bb(coordsPtr+2*(*it3++));
9031 ee->getMiddleOfPoints(aa,bb,tmpp);
9032 addCoo->insertAtTheEnd(tmpp,tmpp+2);
9033 centers.push_back(offset+k);
9037 std::size_t nb(allEdges.size());
9039 throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 2 !");
9040 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9041 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9043 ret->setCoords(coords);
9046 addCoo->rearrange(2);
9047 addCoo=DataArrayDouble::Aggregate(coords,addCoo);
9048 ret->setCoords(addCoo);
9050 ret->allocateCells(1);
9051 std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9052 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9053 connOut[kk]=allEdges[2*kk];
9054 connOut.insert(connOut.end(),centers.begin(),centers.end());
9055 ret->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,connOut.size(),&connOut[0]);
9060 * This method creates a refinement of a cell in \a mesh2D. Those cell is defined by descending connectivity and the sorted subdivided nodal connectivity
9063 * \param [in] mesh2D - The origin 2D mesh. \b Warning \b coords are not those of \a mesh2D. But mesh2D->getCoords()==coords[:mesh2D->getNumberOfNodes()]
9065 MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9067 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(mesh2D->getTypeOfCell(cellIdInMesh2D)));
9068 if(!cm.isQuadratic())
9069 return BuildRefined2DCellLinear(coords,descBg,descEnd,intersectEdge1);
9071 return BuildRefined2DCellQuadratic(coords,mesh2D,cellIdInMesh2D,descBg,descEnd,intersectEdge1);
9074 void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector<int>& conn, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edges)
9077 for(std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >::const_iterator it=edges.begin();it!=edges.end();it++)
9079 const INTERP_KERNEL::Edge *ee(*it);
9080 if(dynamic_cast<const INTERP_KERNEL::EdgeArcCircle *>(ee))
9084 mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]);
9087 const double *coo(mesh2D->getCoords()->begin());
9088 std::size_t sz(conn.size());
9089 std::vector<double> addCoo;
9090 std::vector<int> conn2(conn);
9091 int offset(mesh2D->getNumberOfNodes());
9092 for(std::size_t i=0;i<sz;i++)
9095 edges[(i+1)%sz]->getMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);// tony a chier i+1 -> i
9096 addCoo.insert(addCoo.end(),tmp,tmp+2);
9097 conn2.push_back(offset+(int)i);
9099 mesh2D->getCoords()->rearrange(1);
9100 mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size());
9101 mesh2D->getCoords()->rearrange(2);
9102 mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]);
9107 * \b WARNING edges in out1 coming from \a splitMesh1D are \b NOT oriented because only used for equation of curve.
9109 * This method cuts in 2 parts the input 2D cell given using boundaries description (\a edge1Bis and \a edge1BisPtr) using
9110 * a set of edges defined in \a splitMesh1D.
9112 void BuildMesh2DCutInternal2(const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& edge1Bis, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edge1BisPtr,
9113 std::vector< std::vector<int> >& out0, std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& out1)
9115 std::size_t nb(edge1Bis.size()/2);
9116 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9117 int iEnd(splitMesh1D->getNumberOfCells());
9119 throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal2 : internal error ! input 1D mesh must have at least one cell !");
9121 const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9122 for(ii=0;ii<nb && edge1Bis[2*ii]!=cSplitPtr[ciSplitPtr[0]+1];ii++);
9123 for(jj=ii;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd-1]+2];jj++);
9126 {//the edges splitMesh1D[iStart:iEnd] does not fully cut the current 2D cell -> single output cell
9127 out0.resize(1); out1.resize(1);
9128 std::vector<int>& connOut(out0[0]);
9129 connOut.resize(nbOfEdgesOf2DCellSplit);
9130 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr(out1[0]);
9131 edgesPtr.resize(nbOfEdgesOf2DCellSplit);
9132 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9134 connOut[kk]=edge1Bis[2*kk];
9135 edgesPtr[kk]=edge1BisPtr[2*kk];
9140 // [i,iEnd[ contains the
9141 out0.resize(2); out1.resize(2);
9142 std::vector<int>& connOutLeft(out0[0]);
9143 std::vector<int>& connOutRight(out0[1]);//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1]
9144 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eleft(out1[0]);
9145 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eright(out1[1]);
9146 for(std::size_t k=ii;k<jj+1;k++)
9147 { connOutLeft.push_back(edge1Bis[2*k+1]); eleft.push_back(edge1BisPtr[2*k+1]); }
9148 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > ees(iEnd);
9149 for(int ik=0;ik<iEnd;ik++)
9151 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9152 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9155 for(int ik=iEnd-1;ik>=0;ik--)
9156 connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]);
9157 for(std::size_t k=jj+1;k<nbOfEdgesOf2DCellSplit+ii;k++)
9158 { connOutRight.push_back(edge1Bis[2*k+1]); eright.push_back(edge1BisPtr[2*k+1]); }
9159 eleft.insert(eleft.end(),ees.rbegin(),ees.rend());
9160 for(int ik=0;ik<iEnd;ik++)
9161 connOutRight.push_back(cSplitPtr[ciSplitPtr[ik]+2]);
9162 eright.insert(eright.end(),ees.begin(),ees.end());
9174 CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9176 std::vector<int> _edges;
9177 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > _edges_ptr;
9180 CellInfo::CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr)
9182 std::size_t nbe(edges.size());
9183 std::vector<int> edges2(2*nbe); std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edgesPtr2(2*nbe);
9184 for(std::size_t i=0;i<nbe;i++)
9186 edges2[2*i]=edges[i]; edges2[2*i+1]=edges[(i+1)%nbe];
9187 edgesPtr2[2*i]=edgesPtr[(i+1)%nbe]; edgesPtr2[2*i+1]=edgesPtr[(i+1)%nbe];//tony a chier
9189 _edges.resize(4*nbe); _edges_ptr.resize(4*nbe);
9190 std::copy(edges2.begin(),edges2.end(),_edges.begin()); std::copy(edges2.begin(),edges2.end(),_edges.begin()+2*nbe);
9191 std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()); std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()+2*nbe);
9197 EdgeInfo(int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh):_istart(istart),_iend(iend),_mesh(mesh),_left(-7),_right(-7) { }
9198 EdgeInfo(int istart, int iend, int pos, const MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge>& edge):_istart(istart),_iend(iend),_edge(edge),_left(pos),_right(pos+1) { }
9199 bool isInMyRange(int pos) const { return pos>=_istart && pos<_iend; }
9200 void somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9201 void feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const;
9205 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _mesh;
9206 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> _edge;
9211 void EdgeInfo::somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9213 const MEDCouplingUMesh *mesh(_mesh);
9219 { _left++; _right++; return ; }
9222 bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9223 if((isLeft && isRight) || (!isLeft && !isRight))
9224 throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 1 !");
9235 bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9236 if((isLeft && isRight) || (!isLeft && !isRight))
9237 throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 2 !");
9252 void EdgeInfo::feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const
9254 const MEDCouplingUMesh *mesh(_mesh);
9257 neighbors[0]=offset+_left; neighbors[1]=offset+_right;
9260 {// not fully splitting cell case
9261 if(mesh2D->getNumberOfCells()==1)
9262 {//little optimization. 1 cell no need to find in which cell mesh is !
9263 neighbors[0]=offset; neighbors[1]=offset;
9268 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9269 int cellId(mesh2D->getCellContainingPoint(barys->begin(),eps));
9271 throw INTERP_KERNEL::Exception("EdgeInfo::feedEdgeInfoAt : internal error !");
9272 neighbors[0]=offset+cellId; neighbors[1]=offset+cellId;
9277 class VectorOfCellInfo
9280 VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9281 std::size_t size() const { return _pool.size(); }
9282 int getPositionOf(double eps, const MEDCouplingUMesh *mesh) const;
9283 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);
9284 const std::vector<int>& getConnOf(int pos) const { return get(pos)._edges; }
9285 const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& getEdgePtrOf(int pos) const { return get(pos)._edges_ptr; }
9286 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> getZeMesh() const { return _ze_mesh; }
9287 void feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const;
9289 int getZePosOfEdgeGivenItsGlobalId(int pos) const;
9290 void updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9291 const CellInfo& get(int pos) const;
9292 CellInfo& get(int pos);
9294 std::vector<CellInfo> _pool;
9295 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _ze_mesh;
9296 std::vector<EdgeInfo> _edge_info;
9299 VectorOfCellInfo::VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr):_pool(1)
9301 _pool[0]._edges=edges;
9302 _pool[0]._edges_ptr=edgesPtr;
9305 int VectorOfCellInfo::getPositionOf(double eps, const MEDCouplingUMesh *mesh) const
9308 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : empty !");
9311 const MEDCouplingUMesh *zeMesh(_ze_mesh);
9313 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : null aggregated mesh !");
9314 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9315 return zeMesh->getCellContainingPoint(barys->begin(),eps);
9318 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)
9320 get(pos);//to check pos
9321 bool isFast(pos==0 && _pool.size()==1);
9322 std::size_t sz(edges.size());
9323 // dealing with edges
9325 _edge_info.push_back(EdgeInfo(istart,iend,mesh1DInCase));
9327 _edge_info.push_back(EdgeInfo(istart,iend,pos,edgePtrs[0].back()));
9329 std::vector<CellInfo> pool(_pool.size()-1+sz);
9330 for(int i=0;i<pos;i++)
9332 for(std::size_t j=0;j<sz;j++)
9333 pool[pos+j]=CellInfo(edges[j],edgePtrs[j]);
9334 for(int i=pos+1;i<(int)_pool.size();i++)
9335 pool[i+sz-1]=_pool[i];
9339 updateEdgeInfo(pos,edgePtrs[0],edgePtrs[1]);
9347 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > ms;
9350 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(0,pos,true)));
9354 if(pos<_ze_mesh->getNumberOfCells()-1)
9356 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(pos+1,_ze_mesh->getNumberOfCells(),true)));
9359 std::vector< const MEDCouplingUMesh *> ms2(ms.size());
9360 for(std::size_t j=0;j<ms2.size();j++)
9362 _ze_mesh=MEDCouplingUMesh::MergeUMeshesOnSameCoords(ms2);
9365 void VectorOfCellInfo::feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const
9367 _edge_info[getZePosOfEdgeGivenItsGlobalId(pos)].feedEdgeInfoAt(eps,_ze_mesh,offset,neighbors);
9370 int VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId(int pos) const
9373 throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id ! Must be >=0 !");
9375 for(std::vector<EdgeInfo>::const_iterator it=_edge_info.begin();it!=_edge_info.end();it++,ret++)
9377 if((*it).isInMyRange(pos))
9380 throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id !");
9383 void VectorOfCellInfo::updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9385 get(pos);//to check;
9386 if(_edge_info.empty())
9388 std::size_t sz(_edge_info.size()-1);
9389 for(std::size_t i=0;i<sz;i++)
9390 _edge_info[i].somethingHappendAt(pos,newLeft,newRight);
9393 const CellInfo& VectorOfCellInfo::get(int pos) const
9395 if(pos<0 || pos>=(int)_pool.size())
9396 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get const : invalid pos !");
9400 CellInfo& VectorOfCellInfo::get(int pos)
9402 if(pos<0 || pos>=(int)_pool.size())
9403 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get : invalid pos !");
9409 * - a \b closed set of edges ( \a allEdges and \a allEdgesPtr ) that defines the split descending 2D cell.
9410 * - \a splitMesh1D a split 2D curve mesh contained into 2D cell defined above.
9412 * This method returns the 2D mesh and feeds \a idsLeftRight using offset.
9414 * Algorithm : \a splitMesh1D is cut into contiguous parts. Each contiguous parts will build incrementally the output 2D cells.
9416 * \param [in] allEdges a list of pairs (beginNode, endNode). Linked with \a allEdgesPtr to get the equation of edge.
9418 MEDCouplingUMesh *BuildMesh2DCutInternal(double eps, const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& allEdges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& allEdgesPtr, int offset,
9419 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9421 int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells());
9422 if(nbCellsInSplitMesh1D==0)
9423 throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal : internal error ! input 1D mesh must have at least one cell !");
9424 const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9425 std::size_t nb(allEdges.size()),jj;
9427 throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !");
9428 std::vector<int> edge1Bis(nb*2);
9429 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edge1BisPtr(nb*2);
9430 std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin());
9431 std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb);
9432 std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin());
9433 std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb);
9435 idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(nbCellsInSplitMesh1D*2); idsLeftRight->fillWithValue(-2); idsLeftRight->rearrange(2);
9436 int *idsLeftRightPtr(idsLeftRight->getPointer());
9437 VectorOfCellInfo pool(edge1Bis,edge1BisPtr);
9438 for(int iStart=0;iStart<nbCellsInSplitMesh1D;)
9439 {// split [0:nbCellsInSplitMesh1D) in contiguous parts [iStart:iEnd)
9441 for(;iEnd<nbCellsInSplitMesh1D;)
9443 for(jj=0;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd]+2];jj++);
9449 if(iEnd<nbCellsInSplitMesh1D)
9452 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfSplitMesh1D(static_cast<MEDCouplingUMesh *>(splitMesh1D->buildPartOfMySelf2(iStart,iEnd,1,true)));
9453 int pos(pool.getPositionOf(eps,partOfSplitMesh1D));
9455 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>retTmp(MEDCouplingUMesh::New("",2));
9456 retTmp->setCoords(splitMesh1D->getCoords());
9457 retTmp->allocateCells();
9459 std::vector< std::vector<int> > out0;
9460 std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > > out1;
9462 BuildMesh2DCutInternal2(partOfSplitMesh1D,pool.getConnOf(pos),pool.getEdgePtrOf(pos),out0,out1);
9463 for(std::size_t cnt=0;cnt<out0.size();cnt++)
9464 AddCellInMesh2D(retTmp,out0[cnt],out1[cnt]);
9465 pool.setMeshAt(pos,retTmp,iStart,iEnd,partOfSplitMesh1D,out0,out1);
9469 for(int mm=0;mm<nbCellsInSplitMesh1D;mm++)
9470 pool.feedEdgeInfoAt(eps,mm,offset,idsLeftRightPtr+2*mm);
9471 return pool.getZeMesh().retn();
9474 MEDCouplingUMesh *BuildMesh2DCutFrom(double eps, int cellIdInMesh2D, const MEDCouplingUMesh *mesh2DDesc, const MEDCouplingUMesh *splitMesh1D,
9475 const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1, int offset,
9476 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9478 const int *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin());
9480 std::vector<int> allEdges;
9481 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > allEdgesPtr; // for each sub edge in splitMesh2D the uncut Edge object of the original mesh2D
9482 for(const int *it(descBg);it!=descEnd;it++) // for all edges in the descending connectivity of the 2D mesh in relative Fortran mode
9484 int edgeId(std::abs(*it)-1);
9485 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9486 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m));
9487 const std::vector<int>& edge1(intersectEdge1[edgeId]);
9489 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9491 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9492 std::size_t sz(edge1.size());
9493 for(std::size_t cnt=0;cnt<sz;cnt++)
9494 allEdgesPtr.push_back(ee);
9497 return BuildMesh2DCutInternal(eps,splitMesh1D,allEdges,allEdgesPtr,offset,idsLeftRight);
9500 bool AreEdgeEqual(const double *coo2D, const INTERP_KERNEL::CellModel& typ1, const int *conn1, const INTERP_KERNEL::CellModel& typ2, const int *conn2, double eps)
9502 if(!typ1.isQuadratic() && !typ2.isQuadratic())
9503 {//easy case comparison not
9504 return conn1[0]==conn2[0] && conn1[1]==conn2[1];
9506 else if(typ1.isQuadratic() && typ2.isQuadratic())
9508 bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9511 if(conn1[2]==conn2[2])
9513 const double *a(coo2D+2*conn1[2]),*b(coo2D+2*conn2[2]);
9514 double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9518 {//only one is quadratic
9519 bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9522 const double *a(0),*bb(0),*be(0);
9523 if(typ1.isQuadratic())
9525 a=coo2D+2*conn1[2]; bb=coo2D+2*conn2[0]; be=coo2D+2*conn2[1];
9529 a=coo2D+2*conn2[2]; bb=coo2D+2*conn1[0]; be=coo2D+2*conn1[1];
9531 double b[2]; b[0]=(be[0]+bb[0])/2.; b[1]=(be[1]+bb[1])/2.;
9532 double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9538 * This method returns among the cellIds [ \a candidatesIn2DBg , \a candidatesIn2DEnd ) in \a mesh2DSplit those exactly sharing \a cellIdInMesh1DSplitRelative in \a mesh1DSplit.
9539 * \a mesh2DSplit and \a mesh1DSplit are expected to share the coordinates array.
9541 * \param [in] cellIdInMesh1DSplitRelative is in Fortran mode using sign to specify direction.
9543 int FindRightCandidateAmong(const MEDCouplingUMesh *mesh2DSplit, const int *candidatesIn2DBg, const int *candidatesIn2DEnd, const MEDCouplingUMesh *mesh1DSplit, int cellIdInMesh1DSplitRelative, double eps)
9545 if(candidatesIn2DEnd==candidatesIn2DBg)
9546 throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 1 !");
9547 const double *coo(mesh2DSplit->getCoords()->begin());
9548 if(std::distance(candidatesIn2DBg,candidatesIn2DEnd)==1)
9549 return *candidatesIn2DBg;
9550 int edgeId(std::abs(cellIdInMesh1DSplitRelative)-1);
9551 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur1D(static_cast<MEDCouplingUMesh *>(mesh1DSplit->buildPartOfMySelf(&edgeId,&edgeId+1,true)));
9552 if(cellIdInMesh1DSplitRelative<0)
9553 cur1D->changeOrientationOfCells();
9554 const int *c1D(cur1D->getNodalConnectivity()->begin());
9555 const INTERP_KERNEL::CellModel& ref1DType(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c1D[0]));
9556 for(const int *it=candidatesIn2DBg;it!=candidatesIn2DEnd;it++)
9558 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur2D(static_cast<MEDCouplingUMesh *>(mesh2DSplit->buildPartOfMySelf(it,it+1,true)));
9559 const int *c(cur2D->getNodalConnectivity()->begin()),*ci(cur2D->getNodalConnectivityIndex()->begin());
9560 const INTERP_KERNEL::CellModel &cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[0]]));
9561 unsigned sz(cm.getNumberOfSons2(c+ci[0]+1,ci[1]-ci[0]-1));
9562 INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[1]-ci[0]]);
9563 for(unsigned it2=0;it2<sz;it2++)
9565 INTERP_KERNEL::NormalizedCellType typeOfSon;
9566 cm.fillSonCellNodalConnectivity2(it2,c+ci[0]+1,ci[1]-ci[0]-1,tmpPtr,typeOfSon);
9567 const INTERP_KERNEL::CellModel &curCM(INTERP_KERNEL::CellModel::GetCellModel(typeOfSon));
9568 if(AreEdgeEqual(coo,ref1DType,c1D+1,curCM,tmpPtr,eps))
9572 throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 2 ! Unable to find the edge among split cell !");
9578 * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
9579 * 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
9580 * and finaly, in case of quadratic polygon the centers of edges new nodes.
9581 * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
9583 * \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
9584 * 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)
9585 * \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
9586 * you can invoke orderConsecutiveCells1D on \a mesh1D.
9587 * \param [in] eps - precision used to perform intersections and localization operations.
9588 * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
9589 * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
9590 * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
9591 * 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.
9592 * \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
9593 * and the cell in \a splitMesh2D on the right for the 2nt component. -1 means no cell.
9594 * 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.
9596 * \sa Intersect2DMeshes, orderConsecutiveCells1D, conformize2D, mergeNodes
9598 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
9600 if(!mesh2D || !mesh1D)
9601 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
9602 mesh2D->checkFullyDefined();
9603 mesh1D->checkFullyDefined();
9604 const std::vector<std::string>& compNames(mesh2D->getCoords()->getInfoOnComponents());
9605 if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
9606 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
9607 // Step 1: compute all edge intersections (new nodes)
9608 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9609 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
9610 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9611 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9613 // Build desc connectivity
9614 DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
9615 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9616 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
9617 std::map<int,int> mergedNodes;
9618 Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes);
9619 // use mergeNodes to fix intersectEdge1
9620 for(std::vector< std::vector<int> >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++)
9622 std::size_t n((*it0).size()/2);
9623 int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]);
9624 std::map<int,int>::const_iterator it1;
9625 it1=mergedNodes.find(eltStart);
9626 if(it1!=mergedNodes.end())
9627 (*it0)[0]=(*it1).second;
9628 it1=mergedNodes.find(eltEnd);
9629 if(it1!=mergedNodes.end())
9630 (*it0)[2*n-1]=(*it1).second;
9633 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9634 addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9635 // Step 2: re-order newly created nodes according to the ordering found in m2
9636 std::vector< std::vector<int> > intersectEdge2;
9637 BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
9639 // Step 3: compute splitMesh1D
9640 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear;
9641 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2(DataArrayInt::New()); ret2->alloc(0,1);
9642 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1,
9643 idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear));
9644 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(std::numeric_limits<int>::max()); ret3->rearrange(2);
9645 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells()));
9646 // deal with cells in mesh2D that are not cut but only some of their edges are
9647 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCpy());
9648 idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1);
9649 idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique();
9650 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
9651 if(!idsInDesc2DToBeRefined->empty())
9653 DataArrayInt *out0(0),*outi0(0);
9654 MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
9655 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> outi0s(outi0);
9657 out0s=out0s->buildUnique();
9661 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1NonCol(static_cast<MEDCouplingUMesh *>(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end())));
9662 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> baryRet1(ret1NonCol->getBarycenterAndOwner());
9663 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elts,eltsIndex;
9664 mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
9665 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex2(eltsIndex->deltaShiftIndex());
9666 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex3(eltsIndex2->getIdsEqual(1));
9667 if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells())
9668 throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !");
9669 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToBeModified(elts->buildUnique());
9670 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells()));
9671 if((DataArrayInt *)out0s)
9672 untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one
9673 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > outMesh2DSplit;
9674 // OK all is ready to insert in ret2 mesh
9675 if(!untouchedCells->empty())
9676 {// the most easy part, cells in mesh2D not impacted at all
9677 outMesh2DSplit.push_back(static_cast<MEDCouplingUMesh *>(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end())));
9678 outMesh2DSplit.back()->setCoords(ret1->getCoords());
9679 ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end());
9681 if((DataArrayInt *)out0s)
9682 {// here dealing with cells in out0s but not in cellsToBeModified
9683 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fewModifiedCells(out0s->buildSubstraction(cellsToBeModified));
9684 const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin());
9685 for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++)
9687 outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),mesh2D,*it,dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1));
9688 ret1->setCoords(outMesh2DSplit.back()->getCoords());
9690 int offset(ret2->getNumberOfTuples());
9691 ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end());
9692 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1);
9693 partOfRet3->fillWithValue(std::numeric_limits<int>::max()); partOfRet3->rearrange(2);
9694 int kk(0),*ret3ptr(partOfRet3->getPointer());
9695 for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++)
9697 int faceId(std::abs(*it)-1);
9698 for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++)
9700 int tmp(fewModifiedCells->locateValue(*it2));
9703 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9704 ret3ptr[2*kk]=tmp+offset;
9705 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9706 ret3ptr[2*kk+1]=tmp+offset;
9709 {//the current edge is shared by a 2D cell that will be split just after
9710 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9711 ret3ptr[2*kk]=-(*it2+1);
9712 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9713 ret3ptr[2*kk+1]=-(*it2+1);
9717 m1Desc->setCoords(ret1->getCoords());
9718 ret1NonCol->setCoords(ret1->getCoords());
9719 ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true);
9720 if(!outMesh2DSplit.empty())
9722 DataArrayDouble *da(outMesh2DSplit.back()->getCoords());
9723 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> >::iterator itt=outMesh2DSplit.begin();itt!=outMesh2DSplit.end();itt++)
9724 (*itt)->setCoords(da);
9727 cellsToBeModified=cellsToBeModified->buildUniqueNotSorted();
9728 for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++)
9730 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell(elts->getIdsEqual(*it));
9731 idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end());
9732 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end()));
9733 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfMesh1CuttingCur2DCell(static_cast<MEDCouplingUMesh *>(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end())));
9734 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3;
9735 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));
9736 ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true);
9737 outMesh2DSplit.push_back(splitOfOneCell);
9738 for(int i=0;i<splitOfOneCell->getNumberOfCells();i++)
9739 ret2->pushBackSilent(*it);
9742 std::size_t nbOfMeshes(outMesh2DSplit.size());
9743 std::vector<const MEDCouplingUMesh *> tmp(nbOfMeshes);
9744 for(std::size_t i=0;i<nbOfMeshes;i++)
9745 tmp[i]=outMesh2DSplit[i];
9747 ret1->getCoords()->setInfoOnComponents(compNames);
9748 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2D(MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp));
9749 // To finish - filter ret3 - std::numeric_limits<int>::max() -> -1 - negate values must be resolved.
9751 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> edgesToDealWith(ret3->getIdsStrictlyNegative());
9752 for(const int *it=edgesToDealWith->begin();it!=edgesToDealWith->end();it++)
9754 int old2DCellId(-ret3->getIJ(*it,0)-1);
9755 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates(ret2->getIdsEqual(old2DCellId));
9756 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
9758 ret3->replaceOneValByInThis(std::numeric_limits<int>::max(),-1);
9761 splitMesh1D=ret1.retn();
9762 splitMesh2D=ret2D.retn();
9763 cellIdInMesh2D=ret2.retn();
9764 cellIdInMesh1D=ret3.retn();
9768 * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
9769 * (newly created) nodes corresponding to the edge intersections.
9771 * @param[out] cr, crI connectivity of the resulting mesh
9772 * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
9773 * TODO: describe input parameters
9775 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
9776 const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
9777 const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
9778 const std::vector<double>& addCoords,
9779 std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
9781 static const int SPACEDIM=2;
9782 const double *coo1(m1->getCoords()->getConstPointer());
9783 const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer());
9784 int offset1(m1->getNumberOfNodes());
9785 const double *coo2(m2->getCoords()->getConstPointer());
9786 const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer());
9787 int offset2(offset1+m2->getNumberOfNodes());
9788 int offset3(offset2+((int)addCoords.size())/2);
9789 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
9790 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9791 // Here a BBTree on 2D-cells, not on segments:
9792 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
9793 int ncell1(m1->getNumberOfCells());
9795 for(int i=0;i<ncell1;i++)
9797 std::vector<int> candidates2;
9798 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9799 std::map<INTERP_KERNEL::Node *,int> mapp;
9800 std::map<int,INTERP_KERNEL::Node *> mappRev;
9801 INTERP_KERNEL::QuadraticPolygon pol1;
9802 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
9803 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
9804 // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
9805 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
9806 // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
9807 pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
9808 desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
9810 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
9811 std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
9812 INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
9813 for(it1.first();!it1.finished();it1.next())
9814 edges1.insert(it1.current()->getPtr());
9816 std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
9817 std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
9819 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9821 INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
9822 const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
9823 // Complete mapping with elements coming from the current cell it2 in mesh2:
9824 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
9825 // pol2 is the new QP in the final merged result.
9826 pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
9827 pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
9830 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9832 INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
9833 pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
9834 //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
9835 pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9837 // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
9838 // by m2 but that we still want to keep in the final result.
9843 INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9845 catch(INTERP_KERNEL::Exception& e)
9847 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();
9848 throw INTERP_KERNEL::Exception(oss.str().c_str());
9851 for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
9852 (*it).second->decrRef();
9857 * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
9858 * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
9859 * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
9860 * The caller is to deal with the resulting DataArrayInt.
9861 * \throw If the coordinate array is not set.
9862 * \throw If the nodal connectivity of the cells is not defined.
9863 * \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
9864 * \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
9866 * \sa DataArrayInt::sortEachPairToMakeALinkedList
9868 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
9870 checkFullyDefined();
9871 if(getMeshDimension()!=1)
9872 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
9874 // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
9875 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
9876 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
9877 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
9878 const int *d(_d->getConstPointer()), *dI(_dI->getConstPointer());
9879 const int *rD(_rD->getConstPointer()), *rDI(_rDI->getConstPointer());
9880 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
9881 const int * dsi(_dsi->getConstPointer());
9882 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dsii = _dsi->getIdsNotInRange(0,3);
9884 if (dsii->getNumberOfTuples())
9885 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
9887 int nc(getNumberOfCells());
9888 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> result(DataArrayInt::New());
9889 result->alloc(nc,1);
9891 // set of edges not used so far
9892 std::set<int> edgeSet;
9893 for (int i=0; i<nc; edgeSet.insert(i), i++);
9897 // while we have points with only one neighbor segments
9900 std::list<int> linePiece;
9901 // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
9902 for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
9904 // Fill the list forward (resp. backward) from the start segment:
9905 int activeSeg = startSeg;
9906 int prevPointId = -20;
9908 while (!edgeSet.empty())
9910 if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
9913 linePiece.push_back(activeSeg);
9915 linePiece.push_front(activeSeg);
9916 edgeSet.erase(activeSeg);
9919 int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
9920 ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
9921 if (dsi[ptId] == 1) // hitting the end of the line
9924 int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
9925 activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
9928 // Done, save final piece into DA:
9929 std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
9930 newIdx += linePiece.size();
9932 // identify next valid start segment (one which is not consumed)
9933 if(!edgeSet.empty())
9934 startSeg = *(edgeSet.begin());
9936 while (!edgeSet.empty());
9937 return result.retn();
9942 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
9944 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> nTmp(n); nTmp->incrRef();
9945 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>::const_iterator it(m.find(nTmp));
9947 throw INTERP_KERNEL::Exception("Internal error in remapping !");
9948 int v((*it).second);
9949 if(v==forbVal0 || v==forbVal1)
9951 if(std::find(isect.begin(),isect.end(),v)==isect.end())
9955 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
9960 bool presenceOfOn(false);
9961 for(int i=0;i<sz;i++)
9963 INTERP_KERNEL::ElementaryEdge *e(c[i]);
9964 if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
9966 IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
9967 IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
9969 return presenceOfOn;
9975 * 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.
9976 * 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.
9977 * 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.
9978 * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to avoid to have a non conform mesh.
9980 * \return int - the number of new nodes created (in most of cases 0).
9982 * \throw If \a this is not coherent.
9983 * \throw If \a this has not spaceDim equal to 2.
9984 * \throw If \a this has not meshDim equal to 2.
9985 * \throw If some subcells needed to be split are orphan.
9986 * \sa MEDCouplingUMesh::conformize2D
9988 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
9990 if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
9991 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
9992 desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
9993 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
9994 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
9995 if(midOpt==0 && midOptI==0)
9997 split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
10000 else if(midOpt!=0 && midOptI!=0)
10001 return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
10003 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
10007 * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
10008 * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
10009 * 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
10010 * 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).
10011 * 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.
10013 * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
10014 * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
10016 * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
10017 * This method expects that all nodes in \a this are not closer than \a eps.
10018 * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
10020 * \param [in] eps the relative error to detect merged edges.
10021 * \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
10022 * that the user is expected to deal with.
10024 * \throw If \a this is not coherent.
10025 * \throw If \a this has not spaceDim equal to 2.
10026 * \throw If \a this has not meshDim equal to 2.
10027 * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
10029 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
10031 static const int SPACEDIM=2;
10033 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10034 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10035 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
10036 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
10037 const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
10038 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
10039 const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
10040 int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
10041 std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
10042 std::vector<double> addCoo;
10043 BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
10044 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10045 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10046 for(int i=0;i<nDescCell;i++)
10048 std::vector<int> candidates;
10049 myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
10050 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
10053 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10054 INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
10055 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
10056 INTERP_KERNEL::MergePoints merge;
10057 INTERP_KERNEL::QuadraticPolygon c1,c2;
10058 e1->intersectWith(e2,merge,c1,c2);
10059 e1->decrRef(); e2->decrRef();
10060 if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
10061 overlapEdge[i].push_back(*it);
10062 if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
10063 overlapEdge[*it].push_back(i);
10066 // splitting done. sort intersect point in intersectEdge.
10067 std::vector< std::vector<int> > middle(nDescCell);
10068 int nbOf2DCellsToBeSplit(0);
10069 bool middleNeedsToBeUsed(false);
10070 std::vector<bool> cells2DToTreat(nDescCell,false);
10071 for(int i=0;i<nDescCell;i++)
10073 std::vector<int>& isect(intersectEdge[i]);
10074 int sz((int)isect.size());
10077 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10078 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
10079 e->sortSubNodesAbs(coords,isect);
10084 int idx0(rdi[i]),idx1(rdi[i+1]);
10086 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
10087 if(!cells2DToTreat[rd[idx0]])
10089 cells2DToTreat[rd[idx0]]=true;
10090 nbOf2DCellsToBeSplit++;
10092 // try to reuse at most eventual 'middle' of SEG3
10093 std::vector<int>& mid(middle[i]);
10094 mid.resize(sz+1,-1);
10095 if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
10097 middleNeedsToBeUsed=true;
10098 const std::vector<int>& candidates(overlapEdge[i]);
10099 std::vector<int> trueCandidates;
10100 for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
10101 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
10102 trueCandidates.push_back(*itc);
10103 int stNode(c[ci[i]+1]),endNode(isect[0]);
10104 for(int j=0;j<sz+1;j++)
10106 for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
10108 int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
10109 if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
10110 { mid[j]=*itc; break; }
10113 endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
10118 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
10119 if(nbOf2DCellsToBeSplit==0)
10122 int *retPtr(ret->getPointer());
10123 for(int i=0;i<nCell;i++)
10124 if(cells2DToTreat[i])
10127 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
10128 DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
10129 MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
10130 DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
10131 if(middleNeedsToBeUsed)
10132 { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
10133 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
10134 int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
10135 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.
10136 setPartOfMySelf(ret->begin(),ret->end(),*modif);
10138 bool areNodesMerged; int newNbOfNodes;
10139 if(nbOfNodesCreated!=0)
10140 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
10146 * 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.
10147 * 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).
10148 * 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
10149 * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
10150 * 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
10151 * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
10153 * 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
10154 * using new instance, idem for coordinates.
10156 * 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.
10158 * \return DataArrayInt * - The list of cellIds in \a this that have at least one edge colinearized.
10160 * \throw If \a this is not coherent.
10161 * \throw If \a this has not spaceDim equal to 2.
10162 * \throw If \a this has not meshDim equal to 2.
10164 * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
10166 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
10168 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
10170 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10171 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10172 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10173 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10174 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
10175 const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
10176 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
10177 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
10178 const double *coords(_coords->begin());
10179 int *newciptr(newci->getPointer());
10180 for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
10182 if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
10183 ret->pushBackSilent(i);
10184 newciptr[1]=newc->getNumberOfTuples();
10189 if(!appendedCoords->empty())
10191 appendedCoords->rearrange(2);
10192 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
10194 setCoords(newCoords);
10197 setConnectivity(newc,newci,true);
10202 * \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.
10203 * 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.
10204 * And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
10205 * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
10206 * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
10207 * \param [out] addCoo - nodes to be append at the end
10208 * \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.
10210 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
10211 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)
10213 static const int SPACEDIM=2;
10214 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10215 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10216 const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer());
10217 // Build BB tree of all edges in the tool mesh (second mesh)
10218 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
10219 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10220 int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
10221 intersectEdge1.resize(nDescCell1);
10222 colinear2.resize(nDescCell2);
10223 subDiv2.resize(nDescCell2);
10224 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
10226 std::vector<int> candidates1(1);
10227 int offset1(m1Desc->getNumberOfNodes());
10228 int offset2(offset1+m2Desc->getNumberOfNodes());
10229 for(int i=0;i<nDescCell1;i++) // for all edges in the first mesh
10231 std::vector<int> candidates2; // edges of mesh2 candidate for intersection
10232 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10233 if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
10235 std::map<INTERP_KERNEL::Node *,int> map1,map2;
10236 // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
10237 INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
10239 INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
10240 // 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
10241 // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
10242 std::set<INTERP_KERNEL::Node *> nodes;
10243 pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
10244 std::size_t szz(nodes.size());
10245 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
10246 std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
10247 for(std::size_t iii=0;iii<szz;iii++,itt++)
10248 { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
10249 // end of protection
10250 // Performs egde cutting:
10251 pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes);
10256 // Copy the edge (take only the two first points, ie discard quadratic point at this stage)
10257 intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i]+3);
10262 * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
10263 * It builds the descending connectivity of the two meshes, and then using a binary tree
10264 * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
10265 * Documentation about parameters colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
10267 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
10268 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
10269 MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
10270 std::vector<double>& addCoo,
10271 MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
10273 // Build desc connectivity
10274 desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
10275 desc2=DataArrayInt::New();
10276 descIndx2=DataArrayInt::New();
10277 revDesc2=DataArrayInt::New();
10278 revDescIndx2=DataArrayInt::New();
10279 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
10280 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
10281 m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
10282 m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
10283 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
10284 std::map<int,int> notUsedMap;
10285 Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap);
10286 m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
10287 m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
10291 * This method performs the 2nd step of Partition of 2D mesh.
10292 * This method has 4 inputs :
10293 * - a mesh 'm1' with meshDim==1 and a SpaceDim==2
10294 * - a mesh 'm2' with meshDim==1 and a SpaceDim==2
10295 * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
10296 * 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'
10297 * Nodes end up lying consecutively on a cutted edge.
10298 * \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.
10299 * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
10300 * \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.
10301 * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
10302 * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
10304 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
10305 const std::vector<double>& addCoo,
10306 const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
10308 int offset1=m1->getNumberOfNodes();
10309 int ncell=m2->getNumberOfCells();
10310 const int *c=m2->getNodalConnectivity()->getConstPointer();
10311 const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
10312 const double *coo=m2->getCoords()->getConstPointer();
10313 const double *cooBis=m1->getCoords()->getConstPointer();
10314 int offset2=offset1+m2->getNumberOfNodes();
10315 intersectEdge.resize(ncell);
10316 for(int i=0;i<ncell;i++,cI++)
10318 const std::vector<int>& divs=subDiv[i];
10319 int nnode=cI[1]-cI[0]-1;
10320 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
10321 std::map<INTERP_KERNEL::Node *, int> mapp22;
10322 for(int j=0;j<nnode;j++)
10324 INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
10325 int nnid=c[(*cI)+j+1];
10326 mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
10327 mapp22[nn]=nnid+offset1;
10329 INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
10330 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
10331 ((*it).second.first)->decrRef();
10332 std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
10333 std::map<INTERP_KERNEL::Node *,int> mapp3;
10334 for(std::size_t j=0;j<divs.size();j++)
10337 INTERP_KERNEL::Node *tmp=0;
10339 tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
10340 else if(id<offset2)
10341 tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
10343 tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
10347 e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
10348 for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
10355 * 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).
10356 * 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
10357 * with a plane. The result will be put in 'cut3DSuf' out parameter.
10358 * \param [in] cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
10359 * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
10360 * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
10361 * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
10362 * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
10363 * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
10364 * \param [in] desc is the descending connectivity 3DSurf->3DCurve
10365 * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
10366 * \param [out] cut3DSuf input/output param.
10368 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
10369 const int *nodal3DCurve, const int *nodalIndx3DCurve,
10370 const int *desc, const int *descIndx,
10371 std::vector< std::pair<int,int> >& cut3DSurf)
10373 std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
10374 int nbOf3DSurfCell=(int)cut3DSurf.size();
10375 for(int i=0;i<nbOf3DSurfCell;i++)
10377 std::vector<int> res;
10378 int offset=descIndx[i];
10379 int nbOfSeg=descIndx[i+1]-offset;
10380 for(int j=0;j<nbOfSeg;j++)
10382 int edgeId=desc[offset+j];
10383 int status=cut3DCurve[edgeId];
10387 res.push_back(status);
10390 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
10391 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
10399 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10405 std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
10406 std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
10409 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10413 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
10418 {// case when plane is on a multi colinear edge of a polyhedron
10419 if((int)res.size()==2*nbOfSeg)
10421 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
10424 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
10431 * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
10432 * 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).
10433 * 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
10434 * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
10435 * \param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
10436 * \param desc is the descending connectivity 3D->3DSurf
10437 * \param descIndx is the descending connectivity index 3D->3DSurf
10439 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
10440 const int *desc, const int *descIndx,
10441 DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
10443 checkFullyDefined();
10444 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10445 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
10446 const int *nodal3D=_nodal_connec->getConstPointer();
10447 const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
10448 int nbOfCells=getNumberOfCells();
10449 for(int i=0;i<nbOfCells;i++)
10451 std::map<int, std::set<int> > m;
10452 int offset=descIndx[i];
10453 int nbOfFaces=descIndx[i+1]-offset;
10456 for(int j=0;j<nbOfFaces;j++)
10458 const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
10459 if(p.first!=-1 && p.second!=-1)
10463 start=p.first; end=p.second;
10464 m[p.first].insert(p.second);
10465 m[p.second].insert(p.first);
10469 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
10470 int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
10471 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
10472 INTERP_KERNEL::NormalizedCellType cmsId;
10473 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
10474 start=tmp[0]; end=tmp[nbOfNodesSon-1];
10475 for(unsigned k=0;k<nbOfNodesSon;k++)
10477 m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
10478 m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
10485 std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
10489 std::map<int, std::set<int> >::const_iterator it=m.find(start);
10490 const std::set<int>& s=(*it).second;
10491 std::set<int> s2; s2.insert(prev);
10493 std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
10496 int val=*s3.begin();
10497 conn.push_back(start);
10504 conn.push_back(end);
10507 nodalRes->insertAtTheEnd(conn.begin(),conn.end());
10508 nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
10509 cellIds->pushBackSilent(i);
10515 * 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
10516 * 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
10517 * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
10518 * 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
10519 * 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.
10521 * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
10523 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
10525 std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
10528 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
10529 if(cm.getDimension()==2)
10531 const int *node=nodalConnBg+1;
10532 int startNode=*node++;
10533 double refX=coords[2*startNode];
10534 for(;node!=nodalConnEnd;node++)
10536 if(coords[2*(*node)]<refX)
10539 refX=coords[2*startNode];
10542 std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
10546 double angle0=-M_PI/2;
10551 double angleNext=0.;
10552 while(nextNode!=startNode)
10556 for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
10558 if(*node!=tmpOut.back() && *node!=prevNode)
10560 tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
10561 double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
10566 res=angle0-angleM+2.*M_PI;
10575 if(nextNode!=startNode)
10577 angle0=angleNext-M_PI;
10580 prevNode=tmpOut.back();
10581 tmpOut.push_back(nextNode);
10584 std::vector<int> tmp3(2*(sz-1));
10585 std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
10586 std::copy(nodalConnBg+1,nodalConnEnd,it);
10587 if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
10589 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10592 if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
10594 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10599 nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
10600 nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
10605 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10608 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10612 * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
10613 * 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.
10615 * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
10616 * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
10617 * \param [in,out] arr array in which the remove operation will be done.
10618 * \param [in,out] arrIndx array in the remove operation will modify
10619 * \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])
10620 * \return true if \b arr and \b arrIndx have been modified, false if not.
10622 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
10624 if(!arrIndx || !arr)
10625 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
10626 if(offsetForRemoval<0)
10627 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
10628 std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
10629 int nbOfGrps=arrIndx->getNumberOfTuples()-1;
10630 int *arrIPtr=arrIndx->getPointer();
10632 int previousArrI=0;
10633 const int *arrPtr=arr->getConstPointer();
10634 std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
10635 for(int i=0;i<nbOfGrps;i++,arrIPtr++)
10637 if(*arrIPtr-previousArrI>offsetForRemoval)
10639 for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
10641 if(s.find(*work)==s.end())
10642 arrOut.push_back(*work);
10645 previousArrI=*arrIPtr;
10646 *arrIPtr=(int)arrOut.size();
10648 if(arr->getNumberOfTuples()==(int)arrOut.size())
10650 arr->alloc((int)arrOut.size(),1);
10651 std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
10656 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10657 * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
10658 * The selection of extraction is done standardly in new2old format.
10659 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10661 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10662 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10663 * \param [in] arrIn arr origin array from which the extraction will be done.
10664 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10665 * \param [out] arrOut the resulting array
10666 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10667 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
10669 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10670 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10672 if(!arrIn || !arrIndxIn)
10673 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
10674 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10675 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10676 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
10677 std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
10678 const int *arrInPtr=arrIn->getConstPointer();
10679 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10680 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10682 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10683 int maxSizeOfArr=arrIn->getNumberOfTuples();
10684 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10685 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10686 arrIo->alloc((int)(sz+1),1);
10687 const int *idsIt=idsOfSelectBg;
10688 int *work=arrIo->getPointer();
10691 for(std::size_t i=0;i<sz;i++,work++,idsIt++)
10693 if(*idsIt>=0 && *idsIt<nbOfGrps)
10694 lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
10697 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10698 throw INTERP_KERNEL::Exception(oss.str().c_str());
10704 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
10705 oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
10706 throw INTERP_KERNEL::Exception(oss.str().c_str());
10709 arro->alloc(lgth,1);
10710 work=arro->getPointer();
10711 idsIt=idsOfSelectBg;
10712 for(std::size_t i=0;i<sz;i++,idsIt++)
10714 if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
10715 work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
10718 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
10719 oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10720 throw INTERP_KERNEL::Exception(oss.str().c_str());
10723 arrOut=arro.retn();
10724 arrIndexOut=arrIo.retn();
10728 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10729 * 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 ).
10730 * The selection of extraction is done standardly in new2old format.
10731 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10733 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10734 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10735 * \param [in] arrIn arr origin array from which the extraction will be done.
10736 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10737 * \param [out] arrOut the resulting array
10738 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10739 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
10741 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10742 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10744 if(!arrIn || !arrIndxIn)
10745 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
10746 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10747 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10748 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
10749 int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
10750 const int *arrInPtr=arrIn->getConstPointer();
10751 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10752 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10754 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10755 int maxSizeOfArr=arrIn->getNumberOfTuples();
10756 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10757 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10758 arrIo->alloc((int)(sz+1),1);
10759 int idsIt=idsOfSelectStart;
10760 int *work=arrIo->getPointer();
10763 for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
10765 if(idsIt>=0 && idsIt<nbOfGrps)
10766 lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
10769 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10770 throw INTERP_KERNEL::Exception(oss.str().c_str());
10776 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
10777 oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
10778 throw INTERP_KERNEL::Exception(oss.str().c_str());
10781 arro->alloc(lgth,1);
10782 work=arro->getPointer();
10783 idsIt=idsOfSelectStart;
10784 for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
10786 if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
10787 work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
10790 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
10791 oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10792 throw INTERP_KERNEL::Exception(oss.str().c_str());
10795 arrOut=arro.retn();
10796 arrIndexOut=arrIo.retn();
10800 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10801 * This method 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
10802 * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
10803 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
10805 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10806 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10807 * \param [in] arrIn arr origin array from which the extraction will be done.
10808 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10809 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
10810 * \param [in] srcArrIndex index array of \b srcArr
10811 * \param [out] arrOut the resulting array
10812 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10814 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
10816 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10817 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
10818 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10820 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10821 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
10822 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10823 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10824 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10825 std::vector<bool> v(nbOfTuples,true);
10827 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10828 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10829 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10831 if(*it>=0 && *it<nbOfTuples)
10834 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
10838 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
10839 throw INTERP_KERNEL::Exception(oss.str().c_str());
10842 srcArrIndexPtr=srcArrIndex->getConstPointer();
10843 arrIo->alloc(nbOfTuples+1,1);
10844 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
10845 const int *arrInPtr=arrIn->getConstPointer();
10846 const int *srcArrPtr=srcArr->getConstPointer();
10847 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
10848 int *arroPtr=arro->getPointer();
10849 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
10853 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
10854 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
10858 std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
10859 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
10860 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
10863 arrOut=arro.retn();
10864 arrIndexOut=arrIo.retn();
10868 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10869 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
10871 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10872 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10873 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
10874 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10875 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
10876 * \param [in] srcArrIndex index array of \b srcArr
10878 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
10880 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
10881 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
10883 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10884 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
10885 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10886 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10887 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10888 int *arrInOutPtr=arrInOut->getPointer();
10889 const int *srcArrPtr=srcArr->getConstPointer();
10890 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10892 if(*it>=0 && *it<nbOfTuples)
10894 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
10895 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
10898 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] !";
10899 throw INTERP_KERNEL::Exception(oss.str().c_str());
10904 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
10905 throw INTERP_KERNEL::Exception(oss.str().c_str());
10911 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
10912 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
10913 * 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]].
10914 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
10915 * A negative value in \b arrIn means that it is ignored.
10916 * 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.
10918 * \param [in] arrIn arr origin array from which the extraction will be done.
10919 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10920 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
10921 * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
10923 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
10925 int seed=0,nbOfDepthPeelingPerformed=0;
10926 return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
10930 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
10931 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
10932 * 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]].
10933 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
10934 * A negative value in \b arrIn means that it is ignored.
10935 * 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.
10936 * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
10937 * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
10938 * \param [in] arrIn arr origin array from which the extraction will be done.
10939 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10940 * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
10941 * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
10942 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
10943 * \sa MEDCouplingUMesh::partitionBySpreadZone
10945 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
10947 nbOfDepthPeelingPerformed=0;
10949 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
10950 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10953 DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
10957 std::vector<bool> fetched(nbOfTuples,false);
10958 return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
10961 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
10963 nbOfDepthPeelingPerformed=0;
10964 if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
10965 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
10966 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10967 std::vector<bool> fetched2(nbOfTuples,false);
10969 for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
10971 if(*seedElt>=0 && *seedElt<nbOfTuples)
10972 { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
10974 { 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()); }
10976 const int *arrInPtr=arrIn->getConstPointer();
10977 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10978 int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
10979 std::vector<int> idsToFetch1(seedBg,seedEnd);
10980 std::vector<int> idsToFetch2;
10981 std::vector<int> *idsToFetch=&idsToFetch1;
10982 std::vector<int> *idsToFetchOther=&idsToFetch2;
10983 while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
10985 for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
10986 for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
10988 { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
10989 std::swap(idsToFetch,idsToFetchOther);
10990 idsToFetchOther->clear();
10991 nbOfDepthPeelingPerformed++;
10993 int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
10995 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
10996 int *retPtr=ret->getPointer();
10997 for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
11004 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11005 * 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
11006 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11007 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11009 * \param [in] start begin of set of ids of the input extraction (included)
11010 * \param [in] end end of set of ids of the input extraction (excluded)
11011 * \param [in] step step of the set of ids in range mode.
11012 * \param [in] arrIn arr origin array from which the extraction will be done.
11013 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11014 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11015 * \param [in] srcArrIndex index array of \b srcArr
11016 * \param [out] arrOut the resulting array
11017 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11019 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
11021 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11022 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11023 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11025 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11026 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
11027 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
11028 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
11029 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11031 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11032 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11033 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
11035 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11037 if(it>=0 && it<nbOfTuples)
11038 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
11041 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11042 throw INTERP_KERNEL::Exception(oss.str().c_str());
11045 srcArrIndexPtr=srcArrIndex->getConstPointer();
11046 arrIo->alloc(nbOfTuples+1,1);
11047 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11048 const int *arrInPtr=arrIn->getConstPointer();
11049 const int *srcArrPtr=srcArr->getConstPointer();
11050 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11051 int *arroPtr=arro->getPointer();
11052 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11054 int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
11057 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11058 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11062 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11063 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11066 arrOut=arro.retn();
11067 arrIndexOut=arrIo.retn();
11071 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11072 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11074 * \param [in] start begin of set of ids of the input extraction (included)
11075 * \param [in] end end of set of ids of the input extraction (excluded)
11076 * \param [in] step step of the set of ids in range mode.
11077 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11078 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11079 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11080 * \param [in] srcArrIndex index array of \b srcArr
11082 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11084 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11085 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11087 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11088 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
11089 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11090 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11091 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11092 int *arrInOutPtr=arrInOut->getPointer();
11093 const int *srcArrPtr=srcArr->getConstPointer();
11094 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
11096 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11098 if(it>=0 && it<nbOfTuples)
11100 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
11101 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
11104 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
11105 throw INTERP_KERNEL::Exception(oss.str().c_str());
11110 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11111 throw INTERP_KERNEL::Exception(oss.str().c_str());
11117 * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
11118 * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
11119 * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
11120 * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
11121 * The sum of measure field of returned mesh is equal to the sum of measure field of this.
11123 * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
11125 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
11127 checkFullyDefined();
11128 int mdim=getMeshDimension();
11129 int spaceDim=getSpaceDimension();
11131 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
11132 std::vector<DataArrayInt *> partition=partitionBySpreadZone();
11133 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
11134 std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
11135 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
11136 ret->setCoords(getCoords());
11137 ret->allocateCells((int)partition.size());
11139 for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
11141 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
11142 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
11146 cell=tmp->buildUnionOf2DMesh();
11149 cell=tmp->buildUnionOf3DMesh();
11152 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
11155 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
11158 ret->finishInsertingCells();
11163 * This method partitions \b this into contiguous zone.
11164 * This method only needs a well defined connectivity. Coordinates are not considered here.
11165 * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
11167 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
11169 int nbOfCellsCur=getNumberOfCells();
11170 std::vector<DataArrayInt *> ret;
11171 if(nbOfCellsCur<=0)
11173 DataArrayInt *neigh=0,*neighI=0;
11174 computeNeighborsOfCells(neigh,neighI);
11175 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
11176 std::vector<bool> fetchedCells(nbOfCellsCur,false);
11177 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
11179 while(seed<nbOfCellsCur)
11181 int nbOfPeelPerformed=0;
11182 ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
11183 seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
11185 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
11186 ret.push_back((*it).retn());
11191 * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
11192 * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
11194 * \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.
11195 * \return a newly allocated DataArrayInt to be managed by the caller.
11196 * \throw In case of \a code has not the right format (typically of size 3*n)
11198 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
11200 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
11201 std::size_t nb=code.size()/3;
11202 if(code.size()%3!=0)
11203 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
11204 ret->alloc((int)nb,2);
11205 int *retPtr=ret->getPointer();
11206 for(std::size_t i=0;i<nb;i++,retPtr+=2)
11208 retPtr[0]=code[3*i+2];
11209 retPtr[1]=code[3*i+2]+code[3*i+1];
11215 * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
11216 * All cells in \a this are expected to be linear 3D cells.
11217 * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
11218 * It leads to an increase to number of cells.
11219 * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
11220 * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints
11221 * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
11223 * \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.
11224 * For all other cells, the splitting policy will be ignored.
11225 * \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.
11226 * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
11227 * an id of old cell producing it. The caller is to delete this array using
11228 * decrRef() as it is no more needed.
11229 * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
11231 * \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
11232 * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
11234 * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
11235 * \throw If \a this is not fully constituted with linear 3D cells.
11236 * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
11238 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
11240 INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
11241 checkConnectivityFullyDefined();
11242 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
11243 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
11244 int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
11245 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
11246 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
11247 int *retPt(ret->getPointer());
11248 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
11249 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
11250 const int *oldc(_nodal_connec->begin());
11251 const int *oldci(_nodal_connec_index->begin());
11252 const double *coords(_coords->begin());
11253 for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
11255 std::vector<int> a; std::vector<double> b;
11256 INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
11257 std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
11258 const int *aa(&a[0]);
11261 for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
11263 *it=(-(*(it))-1+nbNodes);
11264 addPts->insertAtTheEnd(b.begin(),b.end());
11265 nbNodes+=(int)b.size()/3;
11267 for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
11268 newConn->insertAtTheEnd(aa,aa+4);
11270 if(!addPts->empty())
11272 addPts->rearrange(3);
11273 nbOfAdditionalPoints=addPts->getNumberOfTuples();
11274 addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
11275 ret0->setCoords(addPts);
11279 nbOfAdditionalPoints=0;
11280 ret0->setCoords(getCoords());
11282 ret0->setNodalConnectivity(newConn);
11284 ret->computeOffsets2();
11285 n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
11286 return ret0.retn();
11290 * 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).
11292 * \sa MEDCouplingUMesh::split2DCells
11294 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
11296 checkConnectivityFullyDefined();
11297 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
11298 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11299 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11300 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11301 int prevPosOfCi(ciPtr[0]);
11302 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11304 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
11305 *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
11306 for(int j=0;j<sz;j++)
11308 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
11309 for(int k=0;k<sz2;k++)
11310 *cPtr++=subPtr[offset2+k];
11312 *cPtr++=oldConn[prevPosOfCi+j+2];
11315 prevPosOfCi=ciPtr[1];
11316 ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11319 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
11320 _nodal_connec->decrRef();
11321 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
11324 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11330 int ret(nodesCnter++);
11332 e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
11333 addCoo.insertAtTheEnd(newPt,newPt+2);
11340 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)
11343 int trueStart(start>=0?start:nbOfEdges+start);
11344 tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
11345 newConnOfCell->insertAtTheEnd(tmp,tmp+3);
11350 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11351 InternalAddPoint(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
11352 middles.push_back(tmp3+offset);
11355 middles.push_back(connBg[trueStart+nbOfEdges]);
11359 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)
11361 int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
11362 newConnOfCell->pushBackSilent(tmpEnd);
11367 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11368 InternalAddPoint(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11369 middles.push_back(tmp3+offset);
11372 middles.push_back(connBg[start+nbOfEdges]);
11376 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)
11382 int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
11383 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11384 InternalAddPoint(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11385 middles.push_back(tmp3+offset);
11388 middles.push_back(connBg[start+nbOfEdges]);
11395 * 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 ) .
11396 * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
11398 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
11400 std::size_t sz(std::distance(connBg,connEnd));
11401 if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
11402 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
11404 INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
11405 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
11406 unsigned nbs(cm.getNumberOfSons2(connBg+1,sz)),nbOfHit(0);
11407 int posBaseElt(0),posEndElt(0),nbOfTurn(0);
11408 INTERP_KERNEL::NormalizedCellType typeOfSon;
11409 std::vector<int> middles;
11411 for(;nbOfHit<nbs;nbOfTurn++)
11413 cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
11414 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
11415 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11418 unsigned endI(nbs-nbOfHit);
11419 for(unsigned i=0;i<endI;i++)
11421 cm.fillSonCellNodalConnectivity2(posBaseElt+(int)i+1,connBg+1,sz,tmpConn,typeOfSon);
11422 INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11423 INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11424 bool isColinear(eint->areColinears());
11436 {//look if the first edge of cell is not colinear with last edges in this case the start of nodal connectivity is shifted back
11437 unsigned endII(nbs-nbOfHit-1);//warning nbOfHit can be modified, so put end condition in a variable.
11438 for(unsigned ii=0;ii<endII;ii++)
11440 cm.fillSonCellNodalConnectivity2(nbs-ii-1,connBg+1,sz,tmpConn,typeOfSon);
11441 eCand=MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m);
11442 eint=INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand);
11443 isColinear=eint->areColinears();
11459 //push [posBaseElt,posEndElt) in newConnOfCell using e
11461 EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11462 else if(nbOfHit!=nbs)
11463 EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11465 EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11466 posBaseElt=posEndElt;
11469 if(!middles.empty())
11470 newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
11475 * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
11477 * \return int - the number of new nodes created.
11478 * \sa MEDCouplingUMesh::split2DCells
11480 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
11483 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
11484 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11485 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
11486 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11487 const int *midPtr(mid->begin()),*midIPtr(midI->begin());
11488 const double *oldCoordsPtr(getCoords()->begin());
11489 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11490 int prevPosOfCi(ciPtr[0]);
11491 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11493 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
11494 for(int j=0;j<sz;j++)
11495 { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
11496 *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
11497 for(int j=0;j<sz;j++)//loop over subedges of oldConn
11499 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
11503 cPtr[1]=oldConn[prevPosOfCi+2+j];
11504 cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
11507 std::vector<INTERP_KERNEL::Node *> ns(3);
11508 ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
11509 ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
11510 ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
11511 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
11512 for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
11514 cPtr[1]=subPtr[offset2+k];
11515 cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
11517 int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
11519 { cPtr[1]=tmpEnd; }
11520 cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
11522 prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
11523 ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11526 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
11527 _nodal_connec->decrRef();
11528 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
11529 addCoo->rearrange(2);
11530 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
11532 return addCoo->getNumberOfTuples();
11535 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
11536 _own_cell(true),_cell_id(-1),_nb_cell(0)
11541 _nb_cell=mesh->getNumberOfCells();
11545 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
11553 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
11554 _own_cell(false),_cell_id(bg-1),
11561 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
11564 if(_cell_id<_nb_cell)
11573 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
11579 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
11581 return new MEDCouplingUMeshCellByTypeIterator(_mesh);
11584 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
11590 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
11598 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
11604 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
11609 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
11614 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
11616 return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
11619 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
11624 _nb_cell=mesh->getNumberOfCells();
11628 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
11635 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
11637 const int *c=_mesh->getNodalConnectivity()->getConstPointer();
11638 const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
11639 if(_cell_id<_nb_cell)
11641 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
11642 int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
11643 int startId=_cell_id;
11644 _cell_id+=nbOfElems;
11645 return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
11651 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
11655 _conn=mesh->getNodalConnectivity()->getPointer();
11656 _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
11660 void MEDCouplingUMeshCell::next()
11662 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11667 _conn_lgth=_conn_indx[1]-_conn_indx[0];
11670 std::string MEDCouplingUMeshCell::repr() const
11672 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11674 std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
11676 std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
11680 return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
11683 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
11685 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11686 return (INTERP_KERNEL::NormalizedCellType)_conn[0];
11688 return INTERP_KERNEL::NORM_ERROR;
11691 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
11694 if(_conn_lgth!=NOTICABLE_FIRST_VAL)