1 // Copyright (C) 2007-2014 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 // Author : Anthony Geay (CEA/DEN)
21 #include "MEDCouplingUMesh.hxx"
22 #include "MEDCoupling1GTUMesh.hxx"
23 #include "MEDCouplingMemArray.txx"
24 #include "MEDCouplingFieldDouble.hxx"
25 #include "CellModel.hxx"
26 #include "VolSurfUser.txx"
27 #include "InterpolationUtils.hxx"
28 #include "PointLocatorAlgos.txx"
30 #include "BBTreeDst.txx"
31 #include "SplitterTetra.hxx"
32 #include "DirectedBoundingBox.hxx"
33 #include "InterpKernelMatrixTools.hxx"
34 #include "InterpKernelMeshQuality.hxx"
35 #include "InterpKernelCellSimplify.hxx"
36 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
37 #include "InterpKernelAutoPtr.hxx"
38 #include "InterpKernelGeo2DNode.hxx"
39 #include "InterpKernelGeo2DEdgeLin.hxx"
40 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
41 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
50 using namespace ParaMEDMEM;
52 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
54 const INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::MEDMEM_ORDER[N_MEDMEM_ORDER] = { INTERP_KERNEL::NORM_POINT1, INTERP_KERNEL::NORM_SEG2, INTERP_KERNEL::NORM_SEG3, INTERP_KERNEL::NORM_SEG4, INTERP_KERNEL::NORM_POLYL, INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_TRI7, INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_QUAD9, INTERP_KERNEL::NORM_POLYGON, INTERP_KERNEL::NORM_QPOLYG, INTERP_KERNEL::NORM_TETRA4, INTERP_KERNEL::NORM_PYRA5, INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXA8, INTERP_KERNEL::NORM_HEXGP12, INTERP_KERNEL::NORM_TETRA10, INTERP_KERNEL::NORM_PYRA13, INTERP_KERNEL::NORM_PENTA15, INTERP_KERNEL::NORM_HEXA20, INTERP_KERNEL::NORM_HEXA27, INTERP_KERNEL::NORM_POLYHED };
56 MEDCouplingUMesh *MEDCouplingUMesh::New()
58 return new MEDCouplingUMesh;
61 MEDCouplingUMesh *MEDCouplingUMesh::New(const std::string& meshName, int meshDim)
63 MEDCouplingUMesh *ret=new MEDCouplingUMesh;
64 ret->setName(meshName);
65 ret->setMeshDimension(meshDim);
70 * Returns a new MEDCouplingMesh which is a full copy of \a this one. No data is shared
71 * between \a this and the new mesh.
72 * \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
73 * delete this mesh using decrRef() as it is no more needed.
75 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
81 * Returns a new MEDCouplingMesh which is a copy of \a this one.
82 * \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
83 * this mesh are shared by the new mesh.
84 * \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
85 * delete this mesh using decrRef() as it is no more needed.
87 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
89 return new MEDCouplingUMesh(*this,recDeepCpy);
93 * This method behaves mostly like MEDCouplingUMesh::deepCpy method, except that only nodal connectivity arrays are deeply copied.
94 * The coordinates are shared between \a this and the returned instance.
96 * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
97 * \sa MEDCouplingUMesh::deepCpy
99 MEDCouplingPointSet *MEDCouplingUMesh::deepCpyConnectivityOnly() const
101 checkConnectivityFullyDefined();
102 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=clone(false);
103 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(getNodalConnectivity()->deepCpy()),ci(getNodalConnectivityIndex()->deepCpy());
104 ret->setConnectivity(c,ci);
108 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other)
111 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
112 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
114 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
115 MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
116 setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
119 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
121 std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
125 std::vector<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildrenWithNull() const
127 std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildrenWithNull());
128 ret.push_back(_nodal_connec);
129 ret.push_back(_nodal_connec_index);
133 void MEDCouplingUMesh::updateTime() const
135 MEDCouplingPointSet::updateTime();
138 updateTimeWith(*_nodal_connec);
140 if(_nodal_connec_index)
142 updateTimeWith(*_nodal_connec_index);
146 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
151 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
152 * then \a this mesh is most probably is writable, exchangeable and available for most
153 * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
154 * this method to check that all is in order with \a this mesh.
155 * \throw If the mesh dimension is not set.
156 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
157 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
158 * \throw If the connectivity data array has more than one component.
159 * \throw If the connectivity data array has a named component.
160 * \throw If the connectivity index data array has more than one component.
161 * \throw If the connectivity index data array has a named component.
163 void MEDCouplingUMesh::checkCoherency() const
166 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
168 MEDCouplingPointSet::checkCoherency();
169 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
171 if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
173 std::ostringstream message;
174 message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
175 throw INTERP_KERNEL::Exception(message.str().c_str());
180 if(_nodal_connec->getNumberOfComponents()!=1)
181 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
182 if(_nodal_connec->getInfoOnComponent(0)!="")
183 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
187 throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
188 if(_nodal_connec_index)
190 if(_nodal_connec_index->getNumberOfComponents()!=1)
191 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
192 if(_nodal_connec_index->getInfoOnComponent(0)!="")
193 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
197 throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
201 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
202 * then \a this mesh is most probably is writable, exchangeable and available for all
203 * algorithms. <br> In addition to the checks performed by checkCoherency(), this
204 * method thoroughly checks the nodal connectivity.
205 * \param [in] eps - a not used parameter.
206 * \throw If the mesh dimension is not set.
207 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
208 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
209 * \throw If the connectivity data array has more than one component.
210 * \throw If the connectivity data array has a named component.
211 * \throw If the connectivity index data array has more than one component.
212 * \throw If the connectivity index data array has a named component.
213 * \throw If number of nodes defining an element does not correspond to the type of element.
214 * \throw If the nodal connectivity includes an invalid node id.
216 void MEDCouplingUMesh::checkCoherency1(double eps) const
221 int meshDim=getMeshDimension();
222 int nbOfNodes=getNumberOfNodes();
223 int nbOfCells=getNumberOfCells();
224 const int *ptr=_nodal_connec->getConstPointer();
225 const int *ptrI=_nodal_connec_index->getConstPointer();
226 for(int i=0;i<nbOfCells;i++)
228 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
229 if((int)cm.getDimension()!=meshDim)
231 std::ostringstream oss;
232 oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
233 throw INTERP_KERNEL::Exception(oss.str().c_str());
235 int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
237 if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
239 std::ostringstream oss;
240 oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " << cm.getNumberOfNodes();
241 oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
242 throw INTERP_KERNEL::Exception(oss.str().c_str());
244 for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
249 if(nodeId>=nbOfNodes)
251 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes !";
252 throw INTERP_KERNEL::Exception(oss.str().c_str());
257 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " in connectivity ! sounds bad !";
258 throw INTERP_KERNEL::Exception(oss.str().c_str());
262 if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
264 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #-1 in connectivity ! sounds bad !";
265 throw INTERP_KERNEL::Exception(oss.str().c_str());
274 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
275 * then \a this mesh is most probably is writable, exchangeable and available for all
276 * algorithms. <br> This method performs the same checks as checkCoherency1() does.
277 * \param [in] eps - a not used parameter.
278 * \throw If the mesh dimension is not set.
279 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
280 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
281 * \throw If the connectivity data array has more than one component.
282 * \throw If the connectivity data array has a named component.
283 * \throw If the connectivity index data array has more than one component.
284 * \throw If the connectivity index data array has a named component.
285 * \throw If number of nodes defining an element does not correspond to the type of element.
286 * \throw If the nodal connectivity includes an invalid node id.
288 void MEDCouplingUMesh::checkCoherency2(double eps) const
290 checkCoherency1(eps);
294 * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
295 * elements contained in the mesh. For more info on the mesh dimension see
296 * \ref MEDCouplingUMeshPage.
297 * \param [in] meshDim - a new mesh dimension.
298 * \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
300 void MEDCouplingUMesh::setMeshDimension(int meshDim)
302 if(meshDim<-1 || meshDim>3)
303 throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
309 * Allocates memory to store an estimation of the given number of cells. Closer is the estimation to the number of cells effectively inserted,
310 * less will be the needs to realloc. If the number of cells to be inserted is not known simply put 0 to this parameter.
311 * If a nodal connectivity previouly existed before the call of this method, it will be reset.
313 * \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
315 * \if ENABLE_EXAMPLES
316 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
317 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
320 void MEDCouplingUMesh::allocateCells(int nbOfCells)
323 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
324 if(_nodal_connec_index)
326 _nodal_connec_index->decrRef();
330 _nodal_connec->decrRef();
332 _nodal_connec_index=DataArrayInt::New();
333 _nodal_connec_index->reserve(nbOfCells+1);
334 _nodal_connec_index->pushBackSilent(0);
335 _nodal_connec=DataArrayInt::New();
336 _nodal_connec->reserve(2*nbOfCells);
342 * Appends a cell to the connectivity array. For deeper understanding what is
343 * happening see \ref MEDCouplingUMeshNodalConnectivity.
344 * \param [in] type - type of cell to add.
345 * \param [in] size - number of nodes constituting this cell.
346 * \param [in] nodalConnOfCell - the connectivity of the cell to add.
348 * \if ENABLE_EXAMPLES
349 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
350 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
353 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
355 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
356 if(_nodal_connec_index==0)
357 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
358 if((int)cm.getDimension()==_mesh_dim)
361 if(size!=(int)cm.getNumberOfNodes())
363 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
364 oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
365 throw INTERP_KERNEL::Exception(oss.str().c_str());
367 int idx=_nodal_connec_index->back();
369 _nodal_connec_index->pushBackSilent(val);
370 _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
375 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
376 oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
377 oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
378 throw INTERP_KERNEL::Exception(oss.str().c_str());
383 * Compacts data arrays to release unused memory. This method is to be called after
384 * finishing cell insertion using \a this->insertNextCell().
386 * \if ENABLE_EXAMPLES
387 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
388 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
391 void MEDCouplingUMesh::finishInsertingCells()
393 _nodal_connec->pack();
394 _nodal_connec_index->pack();
395 _nodal_connec->declareAsNew();
396 _nodal_connec_index->declareAsNew();
401 * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
402 * Useful for python users.
404 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
406 return new MEDCouplingUMeshCellIterator(this);
410 * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
411 * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
412 * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
413 * Useful for python users.
415 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
417 if(!checkConsecutiveCellTypes())
418 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
419 return new MEDCouplingUMeshCellByTypeEntry(this);
423 * Returns a set of all cell types available in \a this mesh.
424 * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
425 * \warning this method does not throw any exception even if \a this is not defined.
426 * \sa MEDCouplingUMesh::getAllGeoTypesSorted
428 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
434 * This method returns the sorted list of geometric types in \a this.
435 * Sorted means in the same order than the cells in \a this. A single entry in return vector means the maximal chunk of consecutive cells in \a this
436 * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
438 * \throw if connectivity in \a this is not correctly defined.
440 * \sa MEDCouplingMesh::getAllGeoTypes
442 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
444 std::vector<INTERP_KERNEL::NormalizedCellType> ret;
445 checkConnectivityFullyDefined();
446 int nbOfCells(getNumberOfCells());
449 if(getMeshLength()<1)
450 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
451 const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
452 ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
453 for(int i=1;i<nbOfCells;i++,ci++)
454 if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
455 ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
460 * This method is a method that compares \a this and \a other.
461 * This method compares \b all attributes, even names and component names.
463 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
466 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
467 std::ostringstream oss; oss.precision(15);
468 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
471 reason="mesh given in input is not castable in MEDCouplingUMesh !";
474 if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
476 if(_mesh_dim!=otherC->_mesh_dim)
478 oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" << otherC->_mesh_dim;
482 if(_types!=otherC->_types)
484 oss << "umesh geometric type mismatch :\nThis geometric types are :";
485 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
486 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
487 oss << "\nOther geometric types are :";
488 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
489 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
493 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
494 if(_nodal_connec==0 || otherC->_nodal_connec==0)
496 reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
499 if(_nodal_connec!=otherC->_nodal_connec)
500 if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
502 reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
505 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
506 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
508 reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
511 if(_nodal_connec_index!=otherC->_nodal_connec_index)
512 if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
514 reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
521 * Checks if data arrays of this mesh (node coordinates, nodal
522 * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
524 * \param [in] other - the mesh to compare with.
525 * \param [in] prec - precision value used to compare node coordinates.
526 * \return bool - \a true if the two meshes are same.
528 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
530 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
533 if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
535 if(_mesh_dim!=otherC->_mesh_dim)
537 if(_types!=otherC->_types)
539 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
540 if(_nodal_connec==0 || otherC->_nodal_connec==0)
542 if(_nodal_connec!=otherC->_nodal_connec)
543 if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
545 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
546 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
548 if(_nodal_connec_index!=otherC->_nodal_connec_index)
549 if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
555 * Checks if \a this and \a other meshes are geometrically equivalent with high
556 * probability, else an exception is thrown. The meshes are considered equivalent if
557 * (1) meshes contain the same number of nodes and the same number of elements of the
558 * same types (2) three cells of the two meshes (first, last and middle) are based
559 * on coincident nodes (with a specified precision).
560 * \param [in] other - the mesh to compare with.
561 * \param [in] prec - the precision used to compare nodes of the two meshes.
562 * \throw If the two meshes do not match.
564 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
566 MEDCouplingPointSet::checkFastEquivalWith(other,prec);
567 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
569 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !");
573 * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
574 * cells each node belongs to.
575 * \warning For speed reasons, this method does not check if node ids in the nodal
576 * connectivity correspond to the size of node coordinates array.
577 * \param [in,out] revNodal - an array holding ids of cells sharing each node.
578 * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
579 * dividing cell ids in \a revNodal into groups each referring to one
580 * node. Its every element (except the last one) is an index pointing to the
581 * first id of a group of cells. For example cells sharing the node #1 are
582 * described by following range of indices:
583 * [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
584 * \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
585 * Number of cells sharing the *i*-th node is
586 * \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
587 * \throw If the coordinates array is not set.
588 * \throw If the nodal connectivity of cells is not defined.
590 * \if ENABLE_EXAMPLES
591 * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
592 * \ref py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
595 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
598 int nbOfNodes=getNumberOfNodes();
599 int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
600 revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
601 std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
602 const int *conn=_nodal_connec->getConstPointer();
603 const int *connIndex=_nodal_connec_index->getConstPointer();
604 int nbOfCells=getNumberOfCells();
605 int nbOfEltsInRevNodal=0;
606 for(int eltId=0;eltId<nbOfCells;eltId++)
608 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
609 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
610 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
611 if(*iter>=0)//for polyhedrons
613 nbOfEltsInRevNodal++;
614 revNodalIndxPtr[(*iter)+1]++;
617 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
618 int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
619 revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
620 std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
621 for(int eltId=0;eltId<nbOfCells;eltId++)
623 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
624 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
625 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
626 if(*iter>=0)//for polyhedrons
627 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
633 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
638 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
644 if(cm.getOrientationStatus(nb,conn1,conn2))
651 class MinusOneSonsGenerator
654 MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
655 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
656 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
657 static const int DELTA=1;
659 const INTERP_KERNEL::CellModel& _cm;
662 class MinusOneSonsGeneratorBiQuadratic
665 MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
666 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
667 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
668 static const int DELTA=1;
670 const INTERP_KERNEL::CellModel& _cm;
673 class MinusTwoSonsGenerator
676 MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
677 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
678 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
679 static const int DELTA=2;
681 const INTERP_KERNEL::CellModel& _cm;
687 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
688 * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
689 * describing correspondence between cells of \a this and the result meshes are
690 * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
691 * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
692 * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
693 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
694 * \warning For speed reasons, this method does not check if node ids in the nodal
695 * connectivity correspond to the size of node coordinates array.
696 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
697 * to write this mesh to the MED file, its cells must be sorted using
698 * sortCellsInMEDFileFrmt().
699 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
700 * each cell of \a this mesh.
701 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
702 * dividing cell ids in \a desc into groups each referring to one
703 * cell of \a this mesh. Its every element (except the last one) is an index
704 * pointing to the first id of a group of cells. For example cells of the
705 * result mesh bounding the cell #1 of \a this mesh are described by following
707 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
708 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
709 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
710 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
711 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
712 * by each cell of the result mesh.
713 * \param [in,out] revDescIndx - the array, of length one more than number of cells
714 * in the result mesh,
715 * dividing cell ids in \a revDesc into groups each referring to one
716 * cell of the result mesh the same way as \a descIndx divides \a desc.
717 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
718 * delete this mesh using decrRef() as it is no more needed.
719 * \throw If the coordinates array is not set.
720 * \throw If the nodal connectivity of cells is node defined.
721 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
722 * revDescIndx == NULL.
724 * \if ENABLE_EXAMPLES
725 * \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
726 * \ref py_mcumesh_buildDescendingConnectivity "Here is a Python example".
728 * \sa buildDescendingConnectivity2()
730 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
732 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
736 * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
737 * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
738 * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
739 * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
740 * \sa MEDCouplingUMesh::buildDescendingConnectivity
742 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
745 if(getMeshDimension()!=3)
746 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
747 return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
751 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
752 * this->getMeshDimension(), that bound cells of \a this mesh. In
753 * addition arrays describing correspondence between cells of \a this and the result
754 * meshes are returned. The arrays \a desc and \a descIndx describe the descending
755 * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
756 * mesh. This method differs from buildDescendingConnectivity() in that apart
757 * from cell ids, \a desc returns mutual orientation of cells in \a this and the
758 * result meshes. So a positive id means that order of nodes in corresponding cells
759 * of two meshes is same, and a negative id means a reverse order of nodes. Since a
760 * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
761 * i.e. cell ids are one-based.
762 * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
763 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
764 * \warning For speed reasons, this method does not check if node ids in the nodal
765 * connectivity correspond to the size of node coordinates array.
766 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
767 * to write this mesh to the MED file, its cells must be sorted using
768 * sortCellsInMEDFileFrmt().
769 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
770 * each cell of \a this mesh.
771 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
772 * dividing cell ids in \a desc into groups each referring to one
773 * cell of \a this mesh. Its every element (except the last one) is an index
774 * pointing to the first id of a group of cells. For example cells of the
775 * result mesh bounding the cell #1 of \a this mesh are described by following
777 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
778 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
779 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
780 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
781 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
782 * by each cell of the result mesh.
783 * \param [in,out] revDescIndx - the array, of length one more than number of cells
784 * in the result mesh,
785 * dividing cell ids in \a revDesc into groups each referring to one
786 * cell of the result mesh the same way as \a descIndx divides \a desc.
787 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
788 * shares the node coordinates array with \a this mesh. The caller is to
789 * delete this mesh using decrRef() as it is no more needed.
790 * \throw If the coordinates array is not set.
791 * \throw If the nodal connectivity of cells is node defined.
792 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
793 * revDescIndx == NULL.
795 * \if ENABLE_EXAMPLES
796 * \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
797 * \ref py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
799 * \sa buildDescendingConnectivity()
801 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
803 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
807 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
808 * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
809 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
810 * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
812 * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
813 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
814 * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
816 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
818 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
819 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
820 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
821 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
822 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
824 ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
828 * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
829 * This method is useful for users that want to reduce along a criterion the set of neighbours cell. This is typically the case to extract a set a neighbours,
830 * excluding a set of meshdim-1 cells in input descending connectivity.
831 * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
832 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
833 * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
835 * \param [in] desc descending connectivity array.
836 * \param [in] descIndx descending connectivity index array used to walk through \b desc.
837 * \param [in] revDesc reverse descending connectivity array.
838 * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
839 * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
840 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
841 * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
843 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
844 DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx)
846 if(!desc || !descIndx || !revDesc || !revDescIndx)
847 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
848 const int *descPtr=desc->getConstPointer();
849 const int *descIPtr=descIndx->getConstPointer();
850 const int *revDescPtr=revDesc->getConstPointer();
851 const int *revDescIPtr=revDescIndx->getConstPointer();
853 int nbCells=descIndx->getNumberOfTuples()-1;
854 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
855 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
856 int *out1Ptr=out1->getPointer();
858 out0->reserve(desc->getNumberOfTuples());
859 for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
861 for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
863 std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
865 out0->insertAtTheEnd(s.begin(),s.end());
867 *out1Ptr=out0->getNumberOfTuples();
869 neighbors=out0.retn();
870 neighborsIndx=out1.retn();
874 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
875 * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
876 * This method lists node by node in \b this which are its neighbors. To compute the result only connectivities are considered.
877 * The neighbor nodes of node having id 'nodeId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
879 * \param [out] neighbors is an array storing all the neighbors of all nodes in \b this. This array is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
880 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
881 * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
883 void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayInt *&neighbors, DataArrayInt *&neighborsIdx) const
886 int mdim(getMeshDimension()),nbNodes(getNumberOfNodes());
887 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descIndx(DataArrayInt::New()),revDesc(DataArrayInt::New()),revDescIndx(DataArrayInt::New());
888 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh1D;
893 mesh1D=explode3DMeshTo1D(desc,descIndx,revDesc,revDescIndx);
898 mesh1D=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
903 mesh1D=const_cast<MEDCouplingUMesh *>(this);
909 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2,1] !");
912 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=0; revDescIndx=0;
913 mesh1D->getReverseNodalConnectivity(desc,descIndx);
914 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0(DataArrayInt::New());
915 ret0->alloc(desc->getNumberOfTuples(),1);
916 int *r0Pt(ret0->getPointer());
917 const int *c1DPtr(mesh1D->getNodalConnectivity()->begin()),*rn(desc->begin()),*rni(descIndx->begin());
918 for(int i=0;i<nbNodes;i++,rni++)
920 for(const int *oneDCellIt=rn+rni[0];oneDCellIt!=rn+rni[1];oneDCellIt++)
921 *r0Pt++=c1DPtr[3*(*oneDCellIt)+1]==i?c1DPtr[3*(*oneDCellIt)+2]:c1DPtr[3*(*oneDCellIt)+1];
923 neighbors=ret0.retn();
924 neighborsIdx=descIndx.retn();
930 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
931 * For speed reasons no check of this will be done.
933 template<class SonsGenerator>
934 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
936 if(!desc || !descIndx || !revDesc || !revDescIndx)
937 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
938 checkConnectivityFullyDefined();
939 int nbOfCells=getNumberOfCells();
940 int nbOfNodes=getNumberOfNodes();
941 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
942 int *revNodalIndxPtr=revNodalIndx->getPointer();
943 const int *conn=_nodal_connec->getConstPointer();
944 const int *connIndex=_nodal_connec_index->getConstPointer();
945 std::string name="Mesh constituent of "; name+=getName();
946 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA);
947 ret->setCoords(getCoords());
948 ret->allocateCells(2*nbOfCells);
949 descIndx->alloc(nbOfCells+1,1);
950 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
951 int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
952 for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
954 int pos=connIndex[eltId];
955 int posP1=connIndex[eltId+1];
956 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
957 SonsGenerator sg(cm);
958 unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
959 INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
960 for(unsigned i=0;i<nbOfSons;i++)
962 INTERP_KERNEL::NormalizedCellType cmsId;
963 unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
964 for(unsigned k=0;k<nbOfNodesSon;k++)
966 revNodalIndxPtr[tmp[k]+1]++;
967 ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
968 revDesc2->pushBackSilent(eltId);
970 descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
972 int nbOfCellsM1=ret->getNumberOfCells();
973 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
974 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
975 std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
976 int *revNodalPtr=revNodal->getPointer();
977 const int *connM1=ret->getNodalConnectivity()->getConstPointer();
978 const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
979 for(int eltId=0;eltId<nbOfCellsM1;eltId++)
981 const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
982 const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
983 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
984 if(*iter>=0)//for polyhedrons
985 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
988 DataArrayInt *commonCells=0,*commonCellsI=0;
989 FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
990 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
991 const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
992 int newNbOfCellsM1=-1;
993 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
994 commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
995 std::vector<bool> isImpacted(nbOfCellsM1,false);
996 for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
997 for(int work2=work[0];work2!=work[1];work2++)
998 isImpacted[commonCellsPtr[work2]]=true;
999 const int *o2nM1Ptr=o2nM1->getConstPointer();
1000 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
1001 const int *n2oM1Ptr=n2oM1->getConstPointer();
1002 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
1003 ret2->copyTinyInfoFrom(this);
1004 desc->alloc(descIndx->back(),1);
1005 int *descPtr=desc->getPointer();
1006 const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
1007 for(int i=0;i<nbOfCellsM1;i++,descPtr++)
1010 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1013 if(i!=n2oM1Ptr[o2nM1Ptr[i]])
1015 const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
1016 *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
1019 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1022 revDesc->reserve(newNbOfCellsM1);
1023 revDescIndx->alloc(newNbOfCellsM1+1,1);
1024 int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
1025 const int *revDesc2Ptr=revDesc2->getConstPointer();
1026 for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
1028 int oldCellIdM1=n2oM1Ptr[i];
1029 if(!isImpacted[oldCellIdM1])
1031 revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
1032 revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
1036 for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
1037 revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
1038 revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
1046 struct MEDCouplingAccVisit
1048 MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1049 int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1050 int _new_nb_of_nodes;
1056 * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1057 * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1058 * array of cell ids. Pay attention that after conversion all algorithms work slower
1059 * with \a this mesh than before conversion. <br> If an exception is thrown during the
1060 * conversion due presence of invalid ids in the array of cells to convert, as a
1061 * result \a this mesh contains some already converted elements. In this case the 2D
1062 * mesh remains valid but 3D mesh becomes \b inconsistent!
1063 * \warning This method can significantly modify the order of geometric types in \a this,
1064 * hence, to write this mesh to the MED file, its cells must be sorted using
1065 * sortCellsInMEDFileFrmt().
1066 * \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1067 * \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1068 * cellIdsToConvertBg.
1069 * \throw If the coordinates array is not set.
1070 * \throw If the nodal connectivity of cells is node defined.
1071 * \throw If dimension of \a this mesh is not either 2 or 3.
1073 * \if ENABLE_EXAMPLES
1074 * \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1075 * \ref py_mcumesh_convertToPolyTypes "Here is a Python example".
1078 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1080 checkFullyDefined();
1081 int dim=getMeshDimension();
1083 throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1084 int nbOfCells(getNumberOfCells());
1087 const int *connIndex=_nodal_connec_index->getConstPointer();
1088 int *conn=_nodal_connec->getPointer();
1089 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1091 if(*iter>=0 && *iter<nbOfCells)
1093 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1094 if(!cm.isQuadratic())
1095 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1097 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1101 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1102 oss << " in range [0," << nbOfCells << ") !";
1103 throw INTERP_KERNEL::Exception(oss.str().c_str());
1109 int *connIndex(_nodal_connec_index->getPointer());
1110 const int *connOld(_nodal_connec->getConstPointer());
1111 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1112 std::vector<bool> toBeDone(nbOfCells,false);
1113 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1115 if(*iter>=0 && *iter<nbOfCells)
1116 toBeDone[*iter]=true;
1119 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1120 oss << " in range [0," << nbOfCells << ") !";
1121 throw INTERP_KERNEL::Exception(oss.str().c_str());
1124 for(int cellId=0;cellId<nbOfCells;cellId++)
1126 int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1127 int lgthOld(posP1-pos-1);
1128 if(toBeDone[cellId])
1130 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1131 unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1132 int *tmp(new int[nbOfFaces*lgthOld+1]);
1133 int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1134 for(unsigned j=0;j<nbOfFaces;j++)
1136 INTERP_KERNEL::NormalizedCellType type;
1137 unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1141 std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1142 connNew->pushBackValsSilent(tmp,tmp+newLgth);
1143 connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1148 connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1149 connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1152 setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1158 * Converts all cells to either polygons (if \a this is a 2D mesh) or
1159 * polyhedrons (if \a this is a 3D mesh).
1160 * \warning As this method is purely for user-friendliness and no optimization is
1161 * done to avoid construction of a useless vector, this method can be costly
1163 * \throw If the coordinates array is not set.
1164 * \throw If the nodal connectivity of cells is node defined.
1165 * \throw If dimension of \a this mesh is not either 2 or 3.
1167 void MEDCouplingUMesh::convertAllToPoly()
1169 int nbOfCells=getNumberOfCells();
1170 std::vector<int> cellIds(nbOfCells);
1171 for(int i=0;i<nbOfCells;i++)
1173 convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1177 * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1178 * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1179 * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1180 * base facet of the volume and the second half of nodes describes an opposite facet
1181 * having the same number of nodes as the base one. This method converts such
1182 * connectivity to a valid polyhedral format where connectivity of each facet is
1183 * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1184 * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1185 * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1186 * a correct orientation of the first facet of a polyhedron, else orientation of a
1187 * corrected cell is reverse.<br>
1188 * This method is useful to build an extruded unstructured mesh with polyhedrons as
1189 * it releases the user from boring description of polyhedra connectivity in the valid
1191 * \throw If \a this->getMeshDimension() != 3.
1192 * \throw If \a this->getSpaceDimension() != 3.
1193 * \throw If the nodal connectivity of cells is not defined.
1194 * \throw If the coordinates array is not set.
1195 * \throw If \a this mesh contains polyhedrons with the valid connectivity.
1196 * \throw If \a this mesh contains polyhedrons with odd number of nodes.
1198 * \if ENABLE_EXAMPLES
1199 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1200 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1203 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1205 checkFullyDefined();
1206 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1207 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1208 int nbOfCells=getNumberOfCells();
1209 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1210 newCi->alloc(nbOfCells+1,1);
1211 int *newci=newCi->getPointer();
1212 const int *ci=_nodal_connec_index->getConstPointer();
1213 const int *c=_nodal_connec->getConstPointer();
1215 for(int i=0;i<nbOfCells;i++)
1217 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1218 if(type==INTERP_KERNEL::NORM_POLYHED)
1220 if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1222 std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1223 throw INTERP_KERNEL::Exception(oss.str().c_str());
1225 std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1228 std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron with 1 face but there is a mismatch of number of nodes in face should be even !";
1229 throw INTERP_KERNEL::Exception(oss.str().c_str());
1232 newci[i+1]=7*n1+2+newci[i];//6*n1 (nodal length) + n1+2 (number of faces) - 1 (number of '-1' separator is equal to number of faces -1) + 1 (for cell type)
1235 newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1237 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1238 newC->alloc(newci[nbOfCells],1);
1239 int *newc=newC->getPointer();
1240 for(int i=0;i<nbOfCells;i++)
1242 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1243 if(type==INTERP_KERNEL::NORM_POLYHED)
1245 std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1246 newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1248 for(std::size_t j=0;j<n1;j++)
1250 newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1252 newc[n1+5*j+1]=c[ci[i]+1+j];
1253 newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1254 newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1255 newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1260 newc=std::copy(c+ci[i],c+ci[i+1],newc);
1262 _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1263 _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1268 * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1269 * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1270 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1271 * to write this mesh to the MED file, its cells must be sorted using
1272 * sortCellsInMEDFileFrmt().
1273 * \return \c true if at least one cell has been converted, \c false else. In the
1274 * last case the nodal connectivity remains unchanged.
1275 * \throw If the coordinates array is not set.
1276 * \throw If the nodal connectivity of cells is not defined.
1277 * \throw If \a this->getMeshDimension() < 0.
1279 bool MEDCouplingUMesh::unPolyze()
1281 checkFullyDefined();
1282 int mdim=getMeshDimension();
1284 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1287 int nbOfCells=getNumberOfCells();
1290 int initMeshLgth=getMeshLength();
1291 int *conn=_nodal_connec->getPointer();
1292 int *index=_nodal_connec_index->getPointer();
1297 for(int i=0;i<nbOfCells;i++)
1299 lgthOfCurCell=index[i+1]-posOfCurCell;
1300 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1301 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1302 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1306 switch(cm.getDimension())
1310 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1311 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1312 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1317 int nbOfFaces,lgthOfPolyhConn;
1318 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1319 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1324 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1328 ret=ret || (newType!=type);
1329 conn[newPos]=newType;
1331 posOfCurCell=index[i+1];
1336 std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1337 newPos+=lgthOfCurCell;
1338 posOfCurCell+=lgthOfCurCell;
1342 if(newPos!=initMeshLgth)
1343 _nodal_connec->reAlloc(newPos);
1350 * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1351 * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1352 * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells.
1354 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not. This epsilon is used to recenter around origin to have maximal
1357 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1359 checkFullyDefined();
1360 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1361 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1362 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1363 coords->recenterForMaxPrecision(eps);
1365 int nbOfCells=getNumberOfCells();
1366 const int *conn=_nodal_connec->getConstPointer();
1367 const int *index=_nodal_connec_index->getConstPointer();
1368 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1369 connINew->alloc(nbOfCells+1,1);
1370 int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1371 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1373 for(int i=0;i<nbOfCells;i++,connINewPtr++)
1375 if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1377 SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1381 connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1382 *connINewPtr=connNew->getNumberOfTuples();
1385 setConnectivity(connNew,connINew,false);
1389 * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1390 * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1391 * the format of returned DataArrayInt instance.
1393 * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1394 * \sa MEDCouplingUMesh::getNodeIdsInUse
1396 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1398 checkConnectivityFullyDefined();
1399 int nbOfCells=getNumberOfCells();
1400 const int *connIndex=_nodal_connec_index->getConstPointer();
1401 const int *conn=_nodal_connec->getConstPointer();
1402 const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1403 int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1404 std::vector<bool> retS(maxElt,false);
1405 for(int i=0;i<nbOfCells;i++)
1406 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1410 for(int i=0;i<maxElt;i++)
1413 DataArrayInt *ret=DataArrayInt::New();
1415 int *retPtr=ret->getPointer();
1416 for(int i=0;i<maxElt;i++)
1423 * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1424 * \sa MEDCouplingUMesh::getNodeIdsInUse
1426 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1428 int nbOfNodes((int)nodeIdsInUse.size()),nbOfCells(getNumberOfCells());
1429 const int *connIndex(_nodal_connec_index->getConstPointer()),*conn(_nodal_connec->getConstPointer());
1430 for(int i=0;i<nbOfCells;i++)
1431 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1434 if(conn[j]<nbOfNodes)
1435 nodeIdsInUse[conn[j]]=true;
1438 std::ostringstream oss; oss << "MEDCouplingUMesh::computeNodeIdsAlg : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1439 throw INTERP_KERNEL::Exception(oss.str().c_str());
1445 * Finds nodes not used in any cell and returns an array giving a new id to every node
1446 * by excluding the unused nodes, for which the array holds -1. The result array is
1447 * a mapping in "Old to New" mode.
1448 * \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1449 * \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1450 * this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1451 * if the node is unused or a new id else. The caller is to delete this
1452 * array using decrRef() as it is no more needed.
1453 * \throw If the coordinates array is not set.
1454 * \throw If the nodal connectivity of cells is not defined.
1455 * \throw If the nodal connectivity includes an invalid id.
1457 * \if ENABLE_EXAMPLES
1458 * \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1459 * \ref py_mcumesh_getNodeIdsInUse "Here is a Python example".
1461 * \sa computeFetchedNodeIds, computeNodeIdsAlg()
1463 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1466 int nbOfNodes(getNumberOfNodes());
1467 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1468 ret->alloc(nbOfNodes,1);
1469 int *traducer=ret->getPointer();
1470 std::fill(traducer,traducer+nbOfNodes,-1);
1471 int nbOfCells=getNumberOfCells();
1472 const int *connIndex=_nodal_connec_index->getConstPointer();
1473 const int *conn=_nodal_connec->getConstPointer();
1474 for(int i=0;i<nbOfCells;i++)
1475 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1478 if(conn[j]<nbOfNodes)
1479 traducer[conn[j]]=1;
1482 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1483 throw INTERP_KERNEL::Exception(oss.str().c_str());
1486 nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1487 std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1492 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1493 * For each cell in \b this the number of nodes constituting cell is computed.
1494 * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1495 * So for pohyhedrons some nodes can be counted several times in the returned result.
1497 * \return a newly allocated array
1498 * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1500 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1502 checkConnectivityFullyDefined();
1503 int nbOfCells=getNumberOfCells();
1504 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1505 ret->alloc(nbOfCells,1);
1506 int *retPtr=ret->getPointer();
1507 const int *conn=getNodalConnectivity()->getConstPointer();
1508 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1509 for(int i=0;i<nbOfCells;i++,retPtr++)
1511 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1512 *retPtr=connI[i+1]-connI[i]-1;
1514 *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1520 * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1521 * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1523 * \return DataArrayInt * - new object to be deallocated by the caller.
1524 * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1526 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1528 checkConnectivityFullyDefined();
1529 int nbOfCells=getNumberOfCells();
1530 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1531 ret->alloc(nbOfCells,1);
1532 int *retPtr=ret->getPointer();
1533 const int *conn=getNodalConnectivity()->getConstPointer();
1534 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1535 for(int i=0;i<nbOfCells;i++,retPtr++)
1537 std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1538 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1539 *retPtr=(int)s.size();
1543 *retPtr=(int)s.size();
1550 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1551 * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1553 * \return a newly allocated array
1555 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1557 checkConnectivityFullyDefined();
1558 int nbOfCells=getNumberOfCells();
1559 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1560 ret->alloc(nbOfCells,1);
1561 int *retPtr=ret->getPointer();
1562 const int *conn=getNodalConnectivity()->getConstPointer();
1563 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1564 for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1566 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1567 *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1573 * Removes unused nodes (the node coordinates array is shorten) and returns an array
1574 * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1575 * array mean that the corresponding old node is no more used.
1576 * \return DataArrayInt * - a new instance of DataArrayInt of length \a
1577 * this->getNumberOfNodes() before call of this method. The caller is to
1578 * delete this array using decrRef() as it is no more needed.
1579 * \throw If the coordinates array is not set.
1580 * \throw If the nodal connectivity of cells is not defined.
1581 * \throw If the nodal connectivity includes an invalid id.
1583 * \if ENABLE_EXAMPLES
1584 * \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1585 * \ref py_mcumesh_zipCoordsTraducer "Here is a Python example".
1588 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1590 return MEDCouplingPointSet::zipCoordsTraducer();
1594 * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1595 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1597 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1602 return AreCellsEqual0(conn,connI,cell1,cell2);
1604 return AreCellsEqual1(conn,connI,cell1,cell2);
1606 return AreCellsEqual2(conn,connI,cell1,cell2);
1608 return AreCellsEqual3(conn,connI,cell1,cell2);
1610 return AreCellsEqual7(conn,connI,cell1,cell2);
1612 throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1616 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1618 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1620 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1621 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1626 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1628 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1630 int sz=connI[cell1+1]-connI[cell1];
1631 if(sz==connI[cell2+1]-connI[cell2])
1633 if(conn[connI[cell1]]==conn[connI[cell2]])
1635 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1636 unsigned dim=cm.getDimension();
1642 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1643 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1644 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1645 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1646 return work!=tmp+sz1?1:0;
1649 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1652 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1659 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1661 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1663 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1665 if(conn[connI[cell1]]==conn[connI[cell2]])
1667 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1668 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1676 * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1678 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1680 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1682 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1683 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1690 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1692 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1694 int sz=connI[cell1+1]-connI[cell1];
1695 if(sz==connI[cell2+1]-connI[cell2])
1697 if(conn[connI[cell1]]==conn[connI[cell2]])
1699 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1700 unsigned dim=cm.getDimension();
1706 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1707 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1708 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1709 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1714 std::reverse_iterator<int *> it1((int *)tmp+sz1);
1715 std::reverse_iterator<int *> it2((int *)tmp);
1716 if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1722 return work!=tmp+sz1?1:0;
1725 {//case of SEG2 and SEG3
1726 if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1728 if(!cm.isQuadratic())
1730 std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1731 std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1732 if(std::equal(it1,it2,conn+connI[cell2]+1))
1738 if(conn[connI[cell1]+1]==conn[connI[cell2]+2] && conn[connI[cell1]+2]==conn[connI[cell2]+1] && conn[connI[cell1]+3]==conn[connI[cell2]+3])
1745 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1752 * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1753 * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1754 * and result remains unchanged.
1755 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1756 * If in 'candidates' pool -1 value is considered as an empty value.
1757 * WARNING this method returns only ONE set of result !
1759 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1761 if(candidates.size()<1)
1764 std::vector<int>::const_iterator iter=candidates.begin();
1765 int start=(*iter++);
1766 for(;iter!=candidates.end();iter++)
1768 int status=AreCellsEqual(conn,connI,start,*iter,compType);
1773 result->pushBackSilent(start);
1777 result->pushBackSilent(*iter);
1779 result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1786 * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1787 * This method keeps the coordiantes of \a this. This method is time consuming and is called
1789 * \param [in] compType input specifying the technique used to compare cells each other.
1790 * - 0 : exactly. A cell is detected to be the same if and only if the connectivity is exactly the same without permutation and types same too. This is the strongest policy.
1791 * - 1 : permutation same orientation. cell1 and cell2 are considered equal if the connectivity of cell2 can be deduced by those of cell1 by direct permutation (with exactly the same orientation)
1792 * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1793 * - 2 : nodal. cell1 and cell2 are equal if and only if cell1 and cell2 have same type and have the same nodes constituting connectivity. This is the laziest policy. This policy
1794 * can be used for users not sensitive to orientation of cell
1795 * \param [in] startCellId specifies the cellId starting from which the equality computation will be carried out. By default it is 0, which it means that all cells in \a this will be scanned.
1796 * \param [out] commonCells
1797 * \param [out] commonCellsI
1798 * \return the correspondance array old to new in a newly allocated array.
1801 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1803 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1804 getReverseNodalConnectivity(revNodal,revNodalI);
1805 FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1808 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1809 DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr)
1811 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1812 int nbOfCells=nodalI->getNumberOfTuples()-1;
1813 commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1814 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1815 const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1816 std::vector<bool> isFetched(nbOfCells,false);
1819 for(int i=0;i<nbOfCells;i++)
1823 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1824 std::vector<int> v,v2;
1825 if(connOfNode!=connPtr+connIPtr[i+1])
1827 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1828 v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1831 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1835 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1836 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1837 v2.resize(std::distance(v2.begin(),it));
1841 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1843 int pos=commonCellsI->back();
1844 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1845 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1846 isFetched[*it]=true;
1854 for(int i=startCellId;i<nbOfCells;i++)
1858 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1859 std::vector<int> v,v2;
1860 if(connOfNode!=connPtr+connIPtr[i+1])
1862 v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1865 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1869 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1870 v2.resize(std::distance(v2.begin(),it));
1874 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1876 int pos=commonCellsI->back();
1877 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1878 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1879 isFetched[*it]=true;
1885 commonCellsArr=commonCells.retn();
1886 commonCellsIArr=commonCellsI.retn();
1890 * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1891 * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1892 * than \a other->getNumberOfCells() in the returned array means that there is no
1893 * corresponding cell in \a this mesh.
1894 * It is expected that \a this and \a other meshes share the same node coordinates
1895 * array, if it is not so an exception is thrown.
1896 * \param [in] other - the mesh to compare with.
1897 * \param [in] compType - specifies a cell comparison technique. For meaning of its
1898 * valid values [0,1,2], see zipConnectivityTraducer().
1899 * \param [out] arr - a new instance of DataArrayInt returning correspondence
1900 * between cells of the two meshes. It contains \a other->getNumberOfCells()
1901 * values. The caller is to delete this array using
1902 * decrRef() as it is no more needed.
1903 * \return bool - \c true if all cells of \a other mesh are present in the \a this
1906 * \if ENABLE_EXAMPLES
1907 * \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1908 * \ref py_mcumesh_areCellsIncludedIn "Here is a Python example".
1910 * \sa checkDeepEquivalOnSameNodesWith()
1911 * \sa checkGeoEquivalWith()
1913 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1915 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1916 int nbOfCells=getNumberOfCells();
1917 static const int possibleCompType[]={0,1,2};
1918 if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1920 std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1921 std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1923 throw INTERP_KERNEL::Exception(oss.str().c_str());
1925 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1926 arr=o2n->substr(nbOfCells);
1927 arr->setName(other->getName());
1929 if(other->getNumberOfCells()==0)
1931 return arr->getMaxValue(tmp)<nbOfCells;
1935 * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1936 * This method tries to determine if \b other is fully included in \b this.
1937 * The main difference is that this method is not expected to throw exception.
1938 * This method has two outputs :
1940 * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1941 * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1943 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1945 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1946 DataArrayInt *commonCells=0,*commonCellsI=0;
1947 int thisNbCells=getNumberOfCells();
1948 mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1949 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1950 const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1951 int otherNbCells=other->getNumberOfCells();
1952 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1953 arr2->alloc(otherNbCells,1);
1954 arr2->fillWithZero();
1955 int *arr2Ptr=arr2->getPointer();
1956 int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1957 for(int i=0;i<nbOfCommon;i++)
1959 int start=commonCellsPtr[commonCellsIPtr[i]];
1960 if(start<thisNbCells)
1962 for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1964 int sig=commonCellsPtr[j]>0?1:-1;
1965 int val=std::abs(commonCellsPtr[j])-1;
1966 if(val>=thisNbCells)
1967 arr2Ptr[val-thisNbCells]=sig*(start+1);
1971 arr2->setName(other->getName());
1972 if(arr2->presenceOfValue(0))
1978 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1981 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1982 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1984 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1985 std::vector<const MEDCouplingUMesh *> ms(2);
1988 return MergeUMeshesOnSameCoords(ms);
1992 * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1993 * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1994 * cellIds is not given explicitely but by a range python like.
1996 * \param keepCoords that specifies if you want or not to keep coords as this or zip it (see ParaMEDMEM::MEDCouplingUMesh::zipCoords). If true zipCoords is \b NOT called, if false, zipCoords is called.
1997 * \return a newly allocated
1999 * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
2000 * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
2002 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const
2004 if(getMeshDimension()!=-1)
2005 return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
2008 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
2010 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2012 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2014 return const_cast<MEDCouplingUMesh *>(this);
2019 * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
2020 * The result mesh shares or not the node coordinates array with \a this mesh depending
2021 * on \a keepCoords parameter.
2022 * \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
2023 * to write this mesh to the MED file, its cells must be sorted using
2024 * sortCellsInMEDFileFrmt().
2025 * \param [in] begin - an array of cell ids to include to the new mesh.
2026 * \param [in] end - a pointer to last-plus-one-th element of \a begin.
2027 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2028 * array of \a this mesh, else "free" nodes are removed from the result mesh
2029 * by calling zipCoords().
2030 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2031 * to delete this mesh using decrRef() as it is no more needed.
2032 * \throw If the coordinates array is not set.
2033 * \throw If the nodal connectivity of cells is not defined.
2034 * \throw If any cell id in the array \a begin is not valid.
2036 * \if ENABLE_EXAMPLES
2037 * \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
2038 * \ref py_mcumesh_buildPartOfMySelf "Here is a Python example".
2041 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2043 if(getMeshDimension()!=-1)
2044 return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
2048 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2050 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2052 return const_cast<MEDCouplingUMesh *>(this);
2057 * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2059 * This method allows to partially modify some cells in \b this (whose list is specified by [ \b cellIdsBg, \b cellIdsEnd ) ) with cells coming in \b otherOnSameCoordsThanThis.
2060 * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2061 * The number of cells of \b this will remain the same with this method.
2063 * \param [in] begin begin of cell ids (included) of cells in this to assign
2064 * \param [in] end end of cell ids (excluded) of cells in this to assign
2065 * \param [in] otherOnSameCoordsThanThis an another mesh with same meshdimension than \b this with exactly the same number of cells than cell ids list in [\b cellIdsBg, \b cellIdsEnd ).
2066 * Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2068 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2070 checkConnectivityFullyDefined();
2071 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2072 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2073 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2074 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2076 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2077 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2078 throw INTERP_KERNEL::Exception(oss.str().c_str());
2080 int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2081 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2083 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2084 throw INTERP_KERNEL::Exception(oss.str().c_str());
2086 int nbOfCells=getNumberOfCells();
2087 bool easyAssign=true;
2088 const int *connI=_nodal_connec_index->getConstPointer();
2089 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2090 for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2092 if(*it>=0 && *it<nbOfCells)
2094 easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2098 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2099 throw INTERP_KERNEL::Exception(oss.str().c_str());
2104 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2109 DataArrayInt *arrOut=0,*arrIOut=0;
2110 MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2112 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2113 setConnectivity(arrOut,arrIOut,true);
2117 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2119 checkConnectivityFullyDefined();
2120 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2121 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2122 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2123 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2125 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2126 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2127 throw INTERP_KERNEL::Exception(oss.str().c_str());
2129 int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2130 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2132 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2133 throw INTERP_KERNEL::Exception(oss.str().c_str());
2135 int nbOfCells=getNumberOfCells();
2136 bool easyAssign=true;
2137 const int *connI=_nodal_connec_index->getConstPointer();
2138 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2140 for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2142 if(it>=0 && it<nbOfCells)
2144 easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2148 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2149 throw INTERP_KERNEL::Exception(oss.str().c_str());
2154 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2159 DataArrayInt *arrOut=0,*arrIOut=0;
2160 MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2162 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2163 setConnectivity(arrOut,arrIOut,true);
2168 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2169 * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2170 * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2171 * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2173 * \param [in] begin input start of array of node ids.
2174 * \param [in] end input end of array of node ids.
2175 * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2176 * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2178 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2180 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2181 checkConnectivityFullyDefined();
2183 int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2184 std::vector<bool> fastFinder(sz,false);
2185 for(const int *work=begin;work!=end;work++)
2186 if(*work>=0 && *work<sz)
2187 fastFinder[*work]=true;
2188 int nbOfCells=getNumberOfCells();
2189 const int *conn=getNodalConnectivity()->getConstPointer();
2190 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2191 for(int i=0;i<nbOfCells;i++)
2193 int ref=0,nbOfHit=0;
2194 for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2198 if(fastFinder[*work2])
2201 if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2202 cellIdsKept->pushBackSilent(i);
2204 cellIdsKeptArr=cellIdsKept.retn();
2208 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2209 * this->getMeshDimension(), that bound some cells of \a this mesh.
2210 * The cells of lower dimension to include to the result mesh are selected basing on
2211 * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2212 * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2213 * ==\c false, a cell is copied if any its node is in the array of node ids. The
2214 * created mesh shares the node coordinates array with \a this mesh.
2215 * \param [in] begin - the array of node ids.
2216 * \param [in] end - a pointer to the (last+1)-th element of \a begin.
2217 * \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2218 * array \a begin are added, else cells whose any node is in the
2219 * array \a begin are added.
2220 * \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2221 * to delete this mesh using decrRef() as it is no more needed.
2222 * \throw If the coordinates array is not set.
2223 * \throw If the nodal connectivity of cells is not defined.
2224 * \throw If any node id in \a begin is not valid.
2226 * \if ENABLE_EXAMPLES
2227 * \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2228 * \ref py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2231 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2233 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2234 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2235 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2236 desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2237 return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2241 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2242 * this->getMeshDimension(), which bound only one cell of \a this mesh.
2243 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2244 * array of \a this mesh, else "free" nodes are removed from the result mesh
2245 * by calling zipCoords().
2246 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2247 * to delete this mesh using decrRef() as it is no more needed.
2248 * \throw If the coordinates array is not set.
2249 * \throw If the nodal connectivity of cells is not defined.
2251 * \if ENABLE_EXAMPLES
2252 * \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2253 * \ref py_mcumesh_buildBoundaryMesh "Here is a Python example".
2256 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2258 DataArrayInt *desc=DataArrayInt::New();
2259 DataArrayInt *descIndx=DataArrayInt::New();
2260 DataArrayInt *revDesc=DataArrayInt::New();
2261 DataArrayInt *revDescIndx=DataArrayInt::New();
2263 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2266 descIndx->decrRef();
2267 int nbOfCells=meshDM1->getNumberOfCells();
2268 const int *revDescIndxC=revDescIndx->getConstPointer();
2269 std::vector<int> boundaryCells;
2270 for(int i=0;i<nbOfCells;i++)
2271 if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2272 boundaryCells.push_back(i);
2273 revDescIndx->decrRef();
2274 MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2279 * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2280 * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2281 * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown.
2283 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2285 checkFullyDefined();
2286 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2287 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2288 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2289 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2291 buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2292 desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2294 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2295 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2296 const int *revDescPtr=revDesc->getConstPointer();
2297 const int *revDescIndxPtr=revDescIndx->getConstPointer();
2298 int nbOfCells=getNumberOfCells();
2299 std::vector<bool> ret1(nbOfCells,false);
2301 for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2302 if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2303 { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2305 DataArrayInt *ret2=DataArrayInt::New();
2307 int *ret2Ptr=ret2->getPointer();
2309 for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2312 ret2->setName("BoundaryCells");
2317 * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2318 * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2319 * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2320 * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2322 * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2323 * This method method returns cells ids set s = s1 + s2 where :
2325 * - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2326 * - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2328 * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2329 * are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2331 * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2332 * \param [out] cellIdsRk1 a newly allocated array containing cells ids of s1+s2 \b into \b cellIdsRk0 subset. To get absolute ids of s1+s2 simply invoke
2333 * cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2335 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2337 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2338 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2339 checkConnectivityFullyDefined();
2340 otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2341 if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2342 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2343 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2344 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2345 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2346 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2347 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2348 const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2349 DataArrayInt *idsOtherInConsti=0;
2350 bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2351 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2353 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2355 for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2356 s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2357 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2358 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2359 DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2360 ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2361 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2362 ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2363 neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2364 RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2365 neighThisPartAuto=0;
2366 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2367 const int li[2]={0,1};
2368 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2369 s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2370 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2373 cellIdsRk0=s0arr.retn();
2374 cellIdsRk1=s_renum1.retn();
2378 * This method computes the skin of \b this. That is to say the consituting meshdim-1 mesh is built and only the boundary subpart is
2379 * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2381 * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2383 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2385 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2386 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2387 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2388 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2390 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2391 revDesc=0; desc=0; descIndx=0;
2392 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2393 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2394 return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2398 * Finds nodes lying on the boundary of \a this mesh.
2399 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2400 * nodes. The caller is to delete this array using decrRef() as it is no
2402 * \throw If the coordinates array is not set.
2403 * \throw If the nodal connectivity of cells is node defined.
2405 * \if ENABLE_EXAMPLES
2406 * \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2407 * \ref py_mcumesh_findBoundaryNodes "Here is a Python example".
2410 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2412 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2413 return skin->computeFetchedNodeIds();
2416 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2419 return const_cast<MEDCouplingUMesh *>(this);
2423 * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2424 * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2425 * This method searches for nodes needed to be duplicated. These nodes are nodes fetched by \b otherDimM1OnSameCoords which are not part of the boundary of \b otherDimM1OnSameCoords.
2426 * If a node is in the boundary of \b this \b and in the boundary of \b otherDimM1OnSameCoords this node is considerd as needed to be duplicated.
2427 * When the set of node ids \b nodeIdsToDuplicate is computed, cell ids in \b this is searched so that their connectivity includes at least 1 node in \b nodeIdsToDuplicate.
2429 * \param [in] otherDimM1OnSameCoords a mesh lying on the same coords than \b this and with a mesh dimension equal to those of \b this minus 1. WARNING this input
2430 * parameter is altered during the call.
2431 * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2432 * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2433 * \param [out] cellIdsNotModified cell ids int \b this that lies on \b otherDimM1OnSameCoords mesh whose connectivity do \b not need to be modified as it is the case for \b cellIdsNeededToBeRenum.
2435 * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2437 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2438 DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const
2440 checkFullyDefined();
2441 otherDimM1OnSameCoords.checkFullyDefined();
2442 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2443 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2444 if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2445 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2446 DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2447 findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2448 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2449 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2450 s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2451 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2452 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2453 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2454 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2455 cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2457 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2458 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2459 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2460 DataArrayInt *idsTmp=0;
2461 bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2462 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2464 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2465 MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2466 DataArrayInt *tmp0=0,*tmp1=0;
2467 ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2468 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2469 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2470 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2471 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2472 cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2473 cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2475 cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2476 cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2477 nodeIdsToDuplicate=s3.retn();
2481 * This method operates a modification of the connectivity and coords in \b this.
2482 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2483 * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2484 * More explicitely the renumber array in nodes is not explicitely given in old2new to avoid to build a big array of renumbering whereas typically few node ids needs to be
2485 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2486 * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2488 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2490 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2491 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2493 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2495 int nbOfNodes=getNumberOfNodes();
2496 duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2497 duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2501 * 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 !");
4632 int oldNbOfNodes=getNumberOfNodes();
4633 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4638 newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4643 newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4647 throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4649 setCoords(newCoords);
4650 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4656 * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4657 * If it is not the case an exception will be thrown.
4658 * This method is non const because the coordinate of \a this can be appended with some new points issued from
4659 * intersection of plane defined by ('origin','vec').
4660 * This method has one in/out parameter : 'cut3DCurve'.
4661 * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4662 * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4663 * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4664 * This method will throw an exception if \a this contains a non linear segment.
4666 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4668 checkFullyDefined();
4669 if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4670 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4671 int ncells=getNumberOfCells();
4672 int nnodes=getNumberOfNodes();
4673 double vec2[3],vec3[3],vec4[3];
4674 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4676 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4677 vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4678 const int *conn=_nodal_connec->getConstPointer();
4679 const int *connI=_nodal_connec_index->getConstPointer();
4680 const double *coo=_coords->getConstPointer();
4681 std::vector<double> addCoo;
4682 for(int i=0;i<ncells;i++)
4684 if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4686 if(cut3DCurve[i]==-2)
4688 int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4689 vec3[0]=coo[3*endd]-coo[3*st]; vec3[1]=coo[3*endd+1]-coo[3*st+1]; vec3[2]=coo[3*endd+2]-coo[3*st+2];
4690 double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4691 double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4692 if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4694 const double *st2=coo+3*st;
4695 vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4696 double pos=-(vec4[0]*vec2[0]+vec4[1]*vec2[1]+vec4[2]*vec2[2])/((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2]));
4697 if(pos>eps && pos<1-eps)
4699 int nNode=((int)addCoo.size())/3;
4700 vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4701 addCoo.insert(addCoo.end(),vec4,vec4+3);
4702 cut3DCurve[i]=nnodes+nNode;
4708 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4712 int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4713 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4714 coo2->alloc(newNbOfNodes,3);
4715 double *tmp=coo2->getPointer();
4716 tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4717 std::copy(addCoo.begin(),addCoo.end(),tmp);
4718 DataArrayDouble::SetArrayIn(coo2,_coords);
4723 * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4724 * \param mesh1D is the input 1D mesh used for translation computation.
4725 * \return newCoords new coords filled by this method.
4727 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4729 int oldNbOfNodes=getNumberOfNodes();
4730 int nbOf1DCells=mesh1D->getNumberOfCells();
4731 int spaceDim=getSpaceDimension();
4732 DataArrayDouble *ret=DataArrayDouble::New();
4733 std::vector<bool> isQuads;
4734 int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4735 ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4736 double *retPtr=ret->getPointer();
4737 const double *coords=getCoords()->getConstPointer();
4738 double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4740 std::vector<double> c;
4744 for(int i=0;i<nbOf1DCells;i++)
4747 mesh1D->getNodeIdsOfCell(i,v);
4749 mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4750 mesh1D->getCoordinatesOfNode(v[0],c);
4751 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4752 for(int j=0;j<oldNbOfNodes;j++)
4753 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4757 mesh1D->getCoordinatesOfNode(v[1],c);
4758 mesh1D->getCoordinatesOfNode(v[0],c);
4759 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4760 for(int j=0;j<oldNbOfNodes;j++)
4761 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4764 ret->copyStringInfoFrom(*getCoords());
4769 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4770 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4771 * \return newCoords new coords filled by this method.
4773 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4775 if(mesh1D->getSpaceDimension()==2)
4776 return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4777 if(mesh1D->getSpaceDimension()==3)
4778 return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4779 throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4783 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4784 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4785 * \return newCoords new coords filled by this method.
4787 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4790 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4791 int oldNbOfNodes=getNumberOfNodes();
4792 int nbOf1DCells=mesh1D->getNumberOfCells();
4794 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4795 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4796 int nbOfLevsInVec=nbOf1DCells+1;
4797 ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4798 double *retPtr=ret->getPointer();
4799 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4800 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4801 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4802 tmp->setCoords(tmp2);
4803 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4804 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4805 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4806 for(int i=1;i<nbOfLevsInVec;i++)
4808 const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4809 const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4810 const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4811 const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4812 tmp->translate(vec);
4813 double tmp3[2],radius,alpha,alpha0;
4814 const double *p0=i+1<nbOfLevsInVec?begin:third;
4815 const double *p1=i+1<nbOfLevsInVec?end:begin;
4816 const double *p2=i+1<nbOfLevsInVec?third:end;
4817 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4818 double cosangle=i+1<nbOfLevsInVec?(p0[0]-tmp3[0])*(p1[0]-tmp3[0])+(p0[1]-tmp3[1])*(p1[1]-tmp3[1]):(p2[0]-tmp3[0])*(p1[0]-tmp3[0])+(p2[1]-tmp3[1])*(p1[1]-tmp3[1]);
4819 double angle=acos(cosangle/(radius*radius));
4820 tmp->rotate(end,0,angle);
4821 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4827 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4828 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4829 * \return newCoords new coords filled by this method.
4831 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4834 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4835 int oldNbOfNodes=getNumberOfNodes();
4836 int nbOf1DCells=mesh1D->getNumberOfCells();
4838 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4839 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4840 int nbOfLevsInVec=nbOf1DCells+1;
4841 ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4842 double *retPtr=ret->getPointer();
4843 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4844 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4845 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4846 tmp->setCoords(tmp2);
4847 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4848 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4849 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4850 for(int i=1;i<nbOfLevsInVec;i++)
4852 const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4853 const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4854 const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4855 const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4856 tmp->translate(vec);
4857 double tmp3[2],radius,alpha,alpha0;
4858 const double *p0=i+1<nbOfLevsInVec?begin:third;
4859 const double *p1=i+1<nbOfLevsInVec?end:begin;
4860 const double *p2=i+1<nbOfLevsInVec?third:end;
4861 double vecPlane[3]={
4862 (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4863 (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4864 (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4866 double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4869 vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4870 double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4871 double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4873 double c2=cos(asin(s2));
4875 {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4876 {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4877 {-vec2[1]*s2, vec2[0]*s2, c2}
4879 double p0r[3]={m[0][0]*p0[0]+m[0][1]*p0[1]+m[0][2]*p0[2], m[1][0]*p0[0]+m[1][1]*p0[1]+m[1][2]*p0[2], m[2][0]*p0[0]+m[2][1]*p0[1]+m[2][2]*p0[2]};
4880 double p1r[3]={m[0][0]*p1[0]+m[0][1]*p1[1]+m[0][2]*p1[2], m[1][0]*p1[0]+m[1][1]*p1[1]+m[1][2]*p1[2], m[2][0]*p1[0]+m[2][1]*p1[1]+m[2][2]*p1[2]};
4881 double p2r[3]={m[0][0]*p2[0]+m[0][1]*p2[1]+m[0][2]*p2[2], m[1][0]*p2[0]+m[1][1]*p2[1]+m[1][2]*p2[2], m[2][0]*p2[0]+m[2][1]*p2[1]+m[2][2]*p2[2]};
4882 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4883 double cosangle=i+1<nbOfLevsInVec?(p0r[0]-tmp3[0])*(p1r[0]-tmp3[0])+(p0r[1]-tmp3[1])*(p1r[1]-tmp3[1]):(p2r[0]-tmp3[0])*(p1r[0]-tmp3[0])+(p2r[1]-tmp3[1])*(p1r[1]-tmp3[1]);
4884 double angle=acos(cosangle/(radius*radius));
4885 tmp->rotate(end,vecPlane,angle);
4887 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4893 * This method is private because not easy to use for end user. This method is const contrary to
4894 * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4895 * the coords sorted slice by slice.
4896 * \param isQuad specifies presence of quadratic cells.
4898 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4900 int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4901 int nbOf2DCells=getNumberOfCells();
4902 int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4903 MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4904 const int *conn=_nodal_connec->getConstPointer();
4905 const int *connI=_nodal_connec_index->getConstPointer();
4906 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4907 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4908 newConnI->alloc(nbOf3DCells+1,1);
4909 int *newConnIPtr=newConnI->getPointer();
4911 std::vector<int> newc;
4912 for(int j=0;j<nbOf2DCells;j++)
4914 AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4915 *newConnIPtr++=(int)newc.size();
4917 newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4918 int *newConnPtr=newConn->getPointer();
4919 int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4920 newConnIPtr=newConnI->getPointer();
4921 for(int iz=0;iz<nbOf1DCells;iz++)
4924 std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4925 for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4927 int icell=(int)(iter-newc.begin());
4928 if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4931 *newConnPtr=(*iter)+iz*deltaPerLev;
4936 *newConnPtr=(*iter);
4939 ret->setConnectivity(newConn,newConnI,true);
4940 ret->setCoords(getCoords());
4945 * Checks if \a this mesh is constituted by only quadratic cells.
4946 * \return bool - \c true if there are only quadratic cells in \a this mesh.
4947 * \throw If the coordinates array is not set.
4948 * \throw If the nodal connectivity of cells is not defined.
4950 bool MEDCouplingUMesh::isFullyQuadratic() const
4952 checkFullyDefined();
4954 int nbOfCells=getNumberOfCells();
4955 for(int i=0;i<nbOfCells && ret;i++)
4957 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4958 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4959 ret=cm.isQuadratic();
4965 * Checks if \a this mesh includes any quadratic cell.
4966 * \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4967 * \throw If the coordinates array is not set.
4968 * \throw If the nodal connectivity of cells is not defined.
4970 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4972 checkFullyDefined();
4974 int nbOfCells=getNumberOfCells();
4975 for(int i=0;i<nbOfCells && !ret;i++)
4977 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4978 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4979 ret=cm.isQuadratic();
4985 * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4986 * this mesh, it remains unchanged.
4987 * \throw If the coordinates array is not set.
4988 * \throw If the nodal connectivity of cells is not defined.
4990 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4992 checkFullyDefined();
4993 int nbOfCells=getNumberOfCells();
4995 const int *iciptr=_nodal_connec_index->getConstPointer();
4996 for(int i=0;i<nbOfCells;i++)
4998 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4999 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5000 if(cm.isQuadratic())
5002 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5003 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5004 if(!cml.isDynamic())
5005 delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
5007 delta+=(iciptr[i+1]-iciptr[i]-1)/2;
5012 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5013 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5014 const int *icptr=_nodal_connec->getConstPointer();
5015 newConn->alloc(getMeshLength()-delta,1);
5016 newConnI->alloc(nbOfCells+1,1);
5017 int *ocptr=newConn->getPointer();
5018 int *ociptr=newConnI->getPointer();
5021 for(int i=0;i<nbOfCells;i++,ociptr++)
5023 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
5024 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5025 if(!cm.isQuadratic())
5027 _types.insert(type);
5028 ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5029 ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5033 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5034 _types.insert(typel);
5035 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5036 int newNbOfNodes=cml.getNumberOfNodes();
5038 newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
5039 *ocptr++=(int)typel;
5040 ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5041 ociptr[1]=ociptr[0]+newNbOfNodes+1;
5044 setConnectivity(newConn,newConnI,false);
5048 * This method converts all linear cell in \a this to quadratic one.
5049 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5050 * 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)
5051 * 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.
5052 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5053 * end of the existing coordinates.
5055 * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5056 * corresponding quadratic cells. 1 is those creating the 'most' complex.
5057 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5059 * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5061 * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5063 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5065 DataArrayInt *conn=0,*connI=0;
5066 DataArrayDouble *coords=0;
5067 std::set<INTERP_KERNEL::NormalizedCellType> types;
5068 checkFullyDefined();
5069 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5070 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5071 int meshDim=getMeshDimension();
5072 switch(conversionType)
5078 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5079 connSafe=conn; connISafe=connI; coordsSafe=coords;
5082 ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5083 connSafe=conn; connISafe=connI; coordsSafe=coords;
5086 ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5087 connSafe=conn; connISafe=connI; coordsSafe=coords;
5090 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5098 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5099 connSafe=conn; connISafe=connI; coordsSafe=coords;
5102 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5103 connSafe=conn; connISafe=connI; coordsSafe=coords;
5106 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5107 connSafe=conn; connISafe=connI; coordsSafe=coords;
5110 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5115 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5117 setConnectivity(connSafe,connISafe,false);
5119 setCoords(coordsSafe);
5125 * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
5126 * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
5127 * The nodes to be added in those 2D cells are defined by the pair of \a nodeIdsToAdd and \a nodeIdsIndexToAdd.
5128 * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
5129 * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
5130 * This method can be seen as the opposite method of colinearize2D.
5131 * 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
5132 * to avoid to modify the numbering of existing nodes.
5134 * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
5135 * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
5136 * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
5137 * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
5138 * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
5139 * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
5140 * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
5142 * \sa buildDescendingConnectivity2
5144 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
5145 const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
5147 if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
5148 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
5149 nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
5150 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
5151 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
5152 if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
5153 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
5154 //DataArrayInt *out0(0),*outi0(0);
5155 //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
5156 //MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s(out0),outi0s(outi0);
5157 //out0s=out0s->buildUnique(); out0s->sort(true);
5162 * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5163 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5164 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5166 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5168 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5169 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5170 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5171 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5172 int nbOfCells=getNumberOfCells();
5173 int nbOfNodes=getNumberOfNodes();
5174 const int *cPtr=_nodal_connec->getConstPointer();
5175 const int *icPtr=_nodal_connec_index->getConstPointer();
5176 int lastVal=0,offset=nbOfNodes;
5177 for(int i=0;i<nbOfCells;i++,icPtr++)
5179 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5180 if(type==INTERP_KERNEL::NORM_SEG2)
5182 types.insert(INTERP_KERNEL::NORM_SEG3);
5183 newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5184 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5185 newConn->pushBackSilent(offset++);
5187 newConnI->pushBackSilent(lastVal);
5188 ret->pushBackSilent(i);
5193 lastVal+=(icPtr[1]-icPtr[0]);
5194 newConnI->pushBackSilent(lastVal);
5195 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5198 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5199 coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5203 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
5205 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5206 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5207 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5209 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5210 DataArrayInt *conn1D=0,*conn1DI=0;
5211 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5212 DataArrayDouble *coordsTmp=0;
5213 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5214 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5215 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5216 const int *c1DPtr=conn1D->begin();
5217 const int *c1DIPtr=conn1DI->begin();
5218 int nbOfCells=getNumberOfCells();
5219 const int *cPtr=_nodal_connec->getConstPointer();
5220 const int *icPtr=_nodal_connec_index->getConstPointer();
5222 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5224 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5225 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5226 if(!cm.isQuadratic())
5228 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5229 types.insert(typ2); newConn->pushBackSilent(typ2);
5230 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5231 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5232 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5233 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5234 newConnI->pushBackSilent(lastVal);
5235 ret->pushBackSilent(i);
5240 lastVal+=(icPtr[1]-icPtr[0]);
5241 newConnI->pushBackSilent(lastVal);
5242 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5245 conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5250 * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5251 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5252 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5254 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5256 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5257 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5258 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5261 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5263 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5264 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5266 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5267 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5268 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5270 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5271 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5272 DataArrayInt *conn1D=0,*conn1DI=0;
5273 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5274 DataArrayDouble *coordsTmp=0;
5275 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5276 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5277 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5278 const int *c1DPtr=conn1D->begin();
5279 const int *c1DIPtr=conn1DI->begin();
5280 int nbOfCells=getNumberOfCells();
5281 const int *cPtr=_nodal_connec->getConstPointer();
5282 const int *icPtr=_nodal_connec_index->getConstPointer();
5283 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5284 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5286 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5287 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5288 if(!cm.isQuadratic())
5290 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5291 types.insert(typ2); newConn->pushBackSilent(typ2);
5292 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5293 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5294 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5295 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5296 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5297 newConnI->pushBackSilent(lastVal);
5298 ret->pushBackSilent(i);
5303 lastVal+=(icPtr[1]-icPtr[0]);
5304 newConnI->pushBackSilent(lastVal);
5305 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5308 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5309 coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5314 * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5315 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5316 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5318 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5320 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5321 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5322 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5325 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5327 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5328 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5329 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5330 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5332 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5333 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5334 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5336 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5337 const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5338 DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5339 std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5340 DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5341 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5342 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5343 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5344 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5345 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5346 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5347 const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5348 int nbOfCells=getNumberOfCells();
5349 const int *cPtr=_nodal_connec->getConstPointer();
5350 const int *icPtr=_nodal_connec_index->getConstPointer();
5351 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5352 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5354 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5355 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5356 if(!cm.isQuadratic())
5358 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5359 if(typ2==INTERP_KERNEL::NORM_ERROR)
5361 std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5362 throw INTERP_KERNEL::Exception(oss.str().c_str());
5364 types.insert(typ2); newConn->pushBackSilent(typ2);
5365 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5366 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5367 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5368 for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5370 int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5371 int tmpPos=newConn->getNumberOfTuples();
5372 newConn->pushBackSilent(nodeId2);
5373 ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5375 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5376 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5377 newConnI->pushBackSilent(lastVal);
5378 ret->pushBackSilent(i);
5383 lastVal+=(icPtr[1]-icPtr[0]);
5384 newConnI->pushBackSilent(lastVal);
5385 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5388 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5389 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5390 coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5391 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5392 std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5393 int *c=newConn->getPointer();
5394 const int *cI(newConnI->begin());
5395 for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5396 c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5397 offset=coordsTmp2Safe->getNumberOfTuples();
5398 for(const int *elt=ret->begin();elt!=ret->end();elt++)
5399 c[cI[(*elt)+1]-1]+=offset;
5400 coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5405 * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5406 * so that the number of cells remains the same. Quadratic faces are converted to
5407 * polygons. This method works only for 2D meshes in
5408 * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5409 * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5410 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5411 * \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5412 * a polylinized edge constituting the input polygon.
5413 * \throw If the coordinates array is not set.
5414 * \throw If the nodal connectivity of cells is not defined.
5415 * \throw If \a this->getMeshDimension() != 2.
5416 * \throw If \a this->getSpaceDimension() != 2.
5418 void MEDCouplingUMesh::tessellate2D(double eps)
5420 checkFullyDefined();
5421 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
5422 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5423 double epsa=fabs(eps);
5424 if(epsa<std::numeric_limits<double>::min())
5425 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 !");
5426 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5427 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5428 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5429 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5430 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5431 revDesc1=0; revDescIndx1=0;
5432 mDesc->tessellate2DCurve(eps);
5433 subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5434 setCoords(mDesc->getCoords());
5438 * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5439 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5440 * \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5441 * a sub-divided edge.
5442 * \throw If the coordinates array is not set.
5443 * \throw If the nodal connectivity of cells is not defined.
5444 * \throw If \a this->getMeshDimension() != 1.
5445 * \throw If \a this->getSpaceDimension() != 2.
5447 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5449 checkFullyDefined();
5450 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5451 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5452 double epsa=fabs(eps);
5453 if(epsa<std::numeric_limits<double>::min())
5454 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 !");
5455 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5456 int nbCells=getNumberOfCells();
5457 int nbNodes=getNumberOfNodes();
5458 const int *conn=_nodal_connec->getConstPointer();
5459 const int *connI=_nodal_connec_index->getConstPointer();
5460 const double *coords=_coords->getConstPointer();
5461 std::vector<double> addCoo;
5462 std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5463 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5464 newConnI->alloc(nbCells+1,1);
5465 int *newConnIPtr=newConnI->getPointer();
5468 INTERP_KERNEL::Node *tmp2[3];
5469 std::set<INTERP_KERNEL::NormalizedCellType> types;
5470 for(int i=0;i<nbCells;i++,newConnIPtr++)
5472 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5473 if(cm.isQuadratic())
5474 {//assert(connI[i+1]-connI[i]-1==3)
5475 tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5476 tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5477 tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5478 tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5479 INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5482 eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5483 types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5485 newConnIPtr[1]=(int)newConn.size();
5489 types.insert(INTERP_KERNEL::NORM_SEG2);
5490 newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5491 newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5492 newConnIPtr[1]=newConnIPtr[0]+3;
5497 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5498 newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5499 newConnIPtr[1]=newConnIPtr[0]+3;
5502 if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5505 DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5506 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5507 newConnArr->alloc((int)newConn.size(),1);
5508 std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5509 DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5510 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5511 newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5512 double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5513 std::copy(addCoo.begin(),addCoo.end(),work);
5514 DataArrayDouble::SetArrayIn(newCoords,_coords);
5519 * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5520 * In addition, returns an array mapping new cells to old ones. <br>
5521 * This method typically increases the number of cells in \a this mesh
5522 * but the number of nodes remains \b unchanged.
5523 * That's why the 3D splitting policies
5524 * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5525 * \param [in] policy - specifies a pattern used for splitting.
5526 * The semantic of \a policy is:
5527 * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5528 * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5529 * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8 into 5 TETRA4 (for 3D mesh only).
5530 * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8 into 6 TETRA4 (for 3D mesh only).
5531 * \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5532 * an id of old cell producing it. The caller is to delete this array using
5533 * decrRef() as it is no more needed.
5534 * \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5535 * \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5536 * and \a this->getMeshDimension() != 3.
5537 * \throw If \a policy is not one of the four discussed above.
5538 * \throw If the nodal connectivity of cells is not defined.
5539 * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5541 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5546 return simplexizePol0();
5548 return simplexizePol1();
5549 case (int) INTERP_KERNEL::PLANAR_FACE_5:
5550 return simplexizePlanarFace5();
5551 case (int) INTERP_KERNEL::PLANAR_FACE_6:
5552 return simplexizePlanarFace6();
5554 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)");
5559 * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5560 * - 1D: INTERP_KERNEL::NORM_SEG2
5561 * - 2D: INTERP_KERNEL::NORM_TRI3
5562 * - 3D: INTERP_KERNEL::NORM_TETRA4.
5564 * This method is useful for users that need to use P1 field services as
5565 * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5566 * All these methods need mesh support containing only simplex cells.
5567 * \return bool - \c true if there are only simplex cells in \a this mesh.
5568 * \throw If the coordinates array is not set.
5569 * \throw If the nodal connectivity of cells is not defined.
5570 * \throw If \a this->getMeshDimension() < 1.
5572 bool MEDCouplingUMesh::areOnlySimplexCells() const
5574 checkFullyDefined();
5575 int mdim=getMeshDimension();
5576 if(mdim<1 || mdim>3)
5577 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5578 int nbCells=getNumberOfCells();
5579 const int *conn=_nodal_connec->getConstPointer();
5580 const int *connI=_nodal_connec_index->getConstPointer();
5581 for(int i=0;i<nbCells;i++)
5583 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5591 * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5593 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5595 checkConnectivityFullyDefined();
5596 if(getMeshDimension()!=2)
5597 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5598 int nbOfCells=getNumberOfCells();
5599 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5600 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5601 ret->alloc(nbOfCells+nbOfCutCells,1);
5602 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5603 int *retPt=ret->getPointer();
5604 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5605 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5606 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5607 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5608 int *pt=newConn->getPointer();
5609 int *ptI=newConnI->getPointer();
5611 const int *oldc=_nodal_connec->getConstPointer();
5612 const int *ci=_nodal_connec_index->getConstPointer();
5613 for(int i=0;i<nbOfCells;i++,ci++)
5615 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5617 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5618 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5619 pt=std::copy(tmp,tmp+8,pt);
5628 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5629 ptI[1]=ptI[0]+ci[1]-ci[0];
5634 _nodal_connec->decrRef();
5635 _nodal_connec=newConn.retn();
5636 _nodal_connec_index->decrRef();
5637 _nodal_connec_index=newConnI.retn();
5644 * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5646 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5648 checkConnectivityFullyDefined();
5649 if(getMeshDimension()!=2)
5650 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5651 int nbOfCells=getNumberOfCells();
5652 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5653 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5654 ret->alloc(nbOfCells+nbOfCutCells,1);
5655 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5656 int *retPt=ret->getPointer();
5657 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5658 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5659 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5660 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5661 int *pt=newConn->getPointer();
5662 int *ptI=newConnI->getPointer();
5664 const int *oldc=_nodal_connec->getConstPointer();
5665 const int *ci=_nodal_connec_index->getConstPointer();
5666 for(int i=0;i<nbOfCells;i++,ci++)
5668 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5670 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5671 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5672 pt=std::copy(tmp,tmp+8,pt);
5681 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5682 ptI[1]=ptI[0]+ci[1]-ci[0];
5687 _nodal_connec->decrRef();
5688 _nodal_connec=newConn.retn();
5689 _nodal_connec_index->decrRef();
5690 _nodal_connec_index=newConnI.retn();
5697 * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5699 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5701 checkConnectivityFullyDefined();
5702 if(getMeshDimension()!=3)
5703 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5704 int nbOfCells=getNumberOfCells();
5705 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5706 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5707 ret->alloc(nbOfCells+4*nbOfCutCells,1);
5708 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5709 int *retPt=ret->getPointer();
5710 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5711 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5712 newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5713 newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5714 int *pt=newConn->getPointer();
5715 int *ptI=newConnI->getPointer();
5717 const int *oldc=_nodal_connec->getConstPointer();
5718 const int *ci=_nodal_connec_index->getConstPointer();
5719 for(int i=0;i<nbOfCells;i++,ci++)
5721 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5723 for(int j=0;j<5;j++,pt+=5,ptI++)
5725 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5726 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];
5733 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5734 ptI[1]=ptI[0]+ci[1]-ci[0];
5739 _nodal_connec->decrRef();
5740 _nodal_connec=newConn.retn();
5741 _nodal_connec_index->decrRef();
5742 _nodal_connec_index=newConnI.retn();
5749 * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5751 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5753 checkConnectivityFullyDefined();
5754 if(getMeshDimension()!=3)
5755 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5756 int nbOfCells=getNumberOfCells();
5757 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5758 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5759 ret->alloc(nbOfCells+5*nbOfCutCells,1);
5760 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5761 int *retPt=ret->getPointer();
5762 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5763 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5764 newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5765 newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5766 int *pt=newConn->getPointer();
5767 int *ptI=newConnI->getPointer();
5769 const int *oldc=_nodal_connec->getConstPointer();
5770 const int *ci=_nodal_connec_index->getConstPointer();
5771 for(int i=0;i<nbOfCells;i++,ci++)
5773 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5775 for(int j=0;j<6;j++,pt+=5,ptI++)
5777 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5778 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];
5785 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5786 ptI[1]=ptI[0]+ci[1]-ci[0];
5791 _nodal_connec->decrRef();
5792 _nodal_connec=newConn.retn();
5793 _nodal_connec_index->decrRef();
5794 _nodal_connec_index=newConnI.retn();
5801 * 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.
5802 * This method completly ignore coordinates.
5803 * \param nodeSubdived is the nodal connectivity of subdivision of edges
5804 * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5805 * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5806 * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5808 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5810 checkFullyDefined();
5811 if(getMeshDimension()!=2)
5812 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5813 int nbOfCells=getNumberOfCells();
5814 int *connI=_nodal_connec_index->getPointer();
5816 for(int i=0;i<nbOfCells;i++,connI++)
5818 int offset=descIndex[i];
5819 int nbOfEdges=descIndex[i+1]-offset;
5821 bool ddirect=desc[offset+nbOfEdges-1]>0;
5822 int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5823 int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5824 for(int j=0;j<nbOfEdges;j++)
5826 bool direct=desc[offset+j]>0;
5827 int edgeId=std::abs(desc[offset+j])-1;
5828 if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5830 int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5831 int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5832 int ref2=direct?id1:id2;
5835 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5836 newConnLgth+=nbOfSubNodes-1;
5841 std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5842 throw INTERP_KERNEL::Exception(oss.str().c_str());
5847 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5850 newConnLgth++;//+1 is for cell type
5851 connI[1]=newConnLgth;
5854 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5855 newConn->alloc(newConnLgth,1);
5856 int *work=newConn->getPointer();
5857 for(int i=0;i<nbOfCells;i++)
5859 *work++=INTERP_KERNEL::NORM_POLYGON;
5860 int offset=descIndex[i];
5861 int nbOfEdges=descIndex[i+1]-offset;
5862 for(int j=0;j<nbOfEdges;j++)
5864 bool direct=desc[offset+j]>0;
5865 int edgeId=std::abs(desc[offset+j])-1;
5867 work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5870 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5871 std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5872 work=std::copy(it,it+nbOfSubNodes-1,work);
5876 DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5879 _types.insert(INTERP_KERNEL::NORM_POLYGON);
5883 * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5884 * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5885 * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5886 * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5887 * so it can be useful to call mergeNodes() before calling this method.
5888 * \throw If \a this->getMeshDimension() <= 1.
5889 * \throw If the coordinates array is not set.
5890 * \throw If the nodal connectivity of cells is not defined.
5892 void MEDCouplingUMesh::convertDegeneratedCells()
5894 checkFullyDefined();
5895 if(getMeshDimension()<=1)
5896 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5897 int nbOfCells=getNumberOfCells();
5900 int initMeshLgth=getMeshLength();
5901 int *conn=_nodal_connec->getPointer();
5902 int *index=_nodal_connec_index->getPointer();
5906 for(int i=0;i<nbOfCells;i++)
5908 lgthOfCurCell=index[i+1]-posOfCurCell;
5909 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5911 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5912 conn+newPos+1,newLgth);
5913 conn[newPos]=newType;
5915 posOfCurCell=index[i+1];
5918 if(newPos!=initMeshLgth)
5919 _nodal_connec->reAlloc(newPos);
5924 * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5925 * A cell is considered to be oriented correctly if an angle between its
5926 * normal vector and a given vector is less than \c PI / \c 2.
5927 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5929 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5931 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5932 * is not cleared before filling in.
5933 * \throw If \a this->getMeshDimension() != 2.
5934 * \throw If \a this->getSpaceDimension() != 3.
5936 * \if ENABLE_EXAMPLES
5937 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5938 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5941 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
5943 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5944 throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5945 int nbOfCells=getNumberOfCells();
5946 const int *conn=_nodal_connec->getConstPointer();
5947 const int *connI=_nodal_connec_index->getConstPointer();
5948 const double *coordsPtr=_coords->getConstPointer();
5949 for(int i=0;i<nbOfCells;i++)
5951 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5952 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5954 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5955 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5962 * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5963 * considered to be oriented correctly if an angle between its normal vector and a
5964 * given vector is less than \c PI / \c 2.
5965 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5967 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5969 * \throw If \a this->getMeshDimension() != 2.
5970 * \throw If \a this->getSpaceDimension() != 3.
5972 * \if ENABLE_EXAMPLES
5973 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5974 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5977 * \sa changeOrientationOfCells
5979 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
5981 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5982 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5983 int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
5984 const int *connI(_nodal_connec_index->getConstPointer());
5985 const double *coordsPtr(_coords->getConstPointer());
5986 bool isModified(false);
5987 for(int i=0;i<nbOfCells;i++)
5989 INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5990 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5992 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
5993 bool isQuadratic(cm.isQuadratic());
5994 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5997 cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6002 _nodal_connec->declareAsNew();
6007 * This method change the orientation of cells in \a this without any consideration of coordinates. Only connectivity is impacted.
6009 * \sa orientCorrectly2DCells
6011 void MEDCouplingUMesh::changeOrientationOfCells()
6013 int mdim(getMeshDimension());
6014 if(mdim!=2 && mdim!=1)
6015 throw INTERP_KERNEL::Exception("Invalid mesh to apply changeOrientationOfCells on it : must be meshDim==2 or meshDim==1 !");
6016 int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6017 const int *connI(_nodal_connec_index->getConstPointer());
6020 for(int i=0;i<nbOfCells;i++)
6022 INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6023 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6024 cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6029 for(int i=0;i<nbOfCells;i++)
6031 INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6032 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6033 cm.changeOrientationOf1D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6039 * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
6040 * oriented facets. The normal vector of the facet should point out of the cell.
6041 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6042 * is not cleared before filling in.
6043 * \throw If \a this->getMeshDimension() != 3.
6044 * \throw If \a this->getSpaceDimension() != 3.
6045 * \throw If the coordinates array is not set.
6046 * \throw If the nodal connectivity of cells is not defined.
6048 * \if ENABLE_EXAMPLES
6049 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6050 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6053 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
6055 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6056 throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
6057 int nbOfCells=getNumberOfCells();
6058 const int *conn=_nodal_connec->getConstPointer();
6059 const int *connI=_nodal_connec_index->getConstPointer();
6060 const double *coordsPtr=_coords->getConstPointer();
6061 for(int i=0;i<nbOfCells;i++)
6063 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6064 if(type==INTERP_KERNEL::NORM_POLYHED)
6066 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6073 * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6075 * \throw If \a this->getMeshDimension() != 3.
6076 * \throw If \a this->getSpaceDimension() != 3.
6077 * \throw If the coordinates array is not set.
6078 * \throw If the nodal connectivity of cells is not defined.
6079 * \throw If the reparation fails.
6081 * \if ENABLE_EXAMPLES
6082 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6083 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6085 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6087 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
6089 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6090 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6091 int nbOfCells=getNumberOfCells();
6092 int *conn=_nodal_connec->getPointer();
6093 const int *connI=_nodal_connec_index->getConstPointer();
6094 const double *coordsPtr=_coords->getConstPointer();
6095 for(int i=0;i<nbOfCells;i++)
6097 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6098 if(type==INTERP_KERNEL::NORM_POLYHED)
6102 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6103 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6105 catch(INTERP_KERNEL::Exception& e)
6107 std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6108 throw INTERP_KERNEL::Exception(oss.str().c_str());
6116 * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6117 * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6118 * according to which the first facet of the cell should be oriented to have the normal vector
6119 * pointing out of cell.
6120 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6121 * cells. The caller is to delete this array using decrRef() as it is no more
6123 * \throw If \a this->getMeshDimension() != 3.
6124 * \throw If \a this->getSpaceDimension() != 3.
6125 * \throw If the coordinates array is not set.
6126 * \throw If the nodal connectivity of cells is not defined.
6128 * \if ENABLE_EXAMPLES
6129 * \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6130 * \ref py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6132 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6134 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6136 const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6137 if(getMeshDimension()!=3)
6138 throw INTERP_KERNEL::Exception(msg);
6139 int spaceDim=getSpaceDimension();
6141 throw INTERP_KERNEL::Exception(msg);
6143 int nbOfCells=getNumberOfCells();
6144 int *conn=_nodal_connec->getPointer();
6145 const int *connI=_nodal_connec_index->getConstPointer();
6146 const double *coo=getCoords()->getConstPointer();
6147 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6148 for(int i=0;i<nbOfCells;i++)
6150 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6151 if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6153 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6155 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6156 cells->pushBackSilent(i);
6160 return cells.retn();
6164 * This method is a faster method to correct orientation of all 3D cells in \a this.
6165 * 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.
6166 * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6168 * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6169 * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons,
6171 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6173 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6174 throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6175 int nbOfCells=getNumberOfCells();
6176 int *conn=_nodal_connec->getPointer();
6177 const int *connI=_nodal_connec_index->getConstPointer();
6178 const double *coordsPtr=_coords->getConstPointer();
6179 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6180 for(int i=0;i<nbOfCells;i++)
6182 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6185 case INTERP_KERNEL::NORM_TETRA4:
6187 if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6189 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6190 ret->pushBackSilent(i);
6194 case INTERP_KERNEL::NORM_PYRA5:
6196 if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6198 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6199 ret->pushBackSilent(i);
6203 case INTERP_KERNEL::NORM_PENTA6:
6204 case INTERP_KERNEL::NORM_HEXA8:
6205 case INTERP_KERNEL::NORM_HEXGP12:
6207 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6209 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6210 ret->pushBackSilent(i);
6214 case INTERP_KERNEL::NORM_POLYHED:
6216 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6218 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6219 ret->pushBackSilent(i);
6224 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 !");
6232 * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6233 * If it is not the case an exception will be thrown.
6234 * This method is fast because the first cell of \a this is used to compute the plane.
6235 * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6236 * \param pos output of size at least 3 used to store a point owned of searched plane.
6238 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6240 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6241 throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6242 const int *conn=_nodal_connec->getConstPointer();
6243 const int *connI=_nodal_connec_index->getConstPointer();
6244 const double *coordsPtr=_coords->getConstPointer();
6245 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6246 std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6250 * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6251 * cells. Currently cells of the following types are treated:
6252 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6253 * For a cell of other type an exception is thrown.
6254 * Space dimension of a 2D mesh can be either 2 or 3.
6255 * The Edge Ratio of a cell \f$t\f$ is:
6256 * \f$\frac{|t|_\infty}{|t|_0}\f$,
6257 * where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6258 * the smallest edge lengths of \f$t\f$.
6259 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6260 * cells and one time, lying on \a this mesh. The caller is to delete this
6261 * field using decrRef() as it is no more needed.
6262 * \throw If the coordinates array is not set.
6263 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6264 * \throw If the connectivity data array has more than one component.
6265 * \throw If the connectivity data array has a named component.
6266 * \throw If the connectivity index data array has more than one component.
6267 * \throw If the connectivity index data array has a named component.
6268 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6269 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6270 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6272 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6275 int spaceDim=getSpaceDimension();
6276 int meshDim=getMeshDimension();
6277 if(spaceDim!=2 && spaceDim!=3)
6278 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6279 if(meshDim!=2 && meshDim!=3)
6280 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6281 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6283 int nbOfCells=getNumberOfCells();
6284 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6285 arr->alloc(nbOfCells,1);
6286 double *pt=arr->getPointer();
6287 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6288 const int *conn=_nodal_connec->getConstPointer();
6289 const int *connI=_nodal_connec_index->getConstPointer();
6290 const double *coo=_coords->getConstPointer();
6292 for(int i=0;i<nbOfCells;i++,pt++)
6294 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6297 case INTERP_KERNEL::NORM_TRI3:
6299 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6300 *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6303 case INTERP_KERNEL::NORM_QUAD4:
6305 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6306 *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6309 case INTERP_KERNEL::NORM_TETRA4:
6311 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6312 *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6316 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6318 conn+=connI[i+1]-connI[i];
6320 ret->setName("EdgeRatio");
6321 ret->synchronizeTimeWithSupport();
6326 * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6327 * cells. Currently cells of the following types are treated:
6328 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6329 * For a cell of other type an exception is thrown.
6330 * Space dimension of a 2D mesh can be either 2 or 3.
6331 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6332 * cells and one time, lying on \a this mesh. The caller is to delete this
6333 * field using decrRef() as it is no more needed.
6334 * \throw If the coordinates array is not set.
6335 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6336 * \throw If the connectivity data array has more than one component.
6337 * \throw If the connectivity data array has a named component.
6338 * \throw If the connectivity index data array has more than one component.
6339 * \throw If the connectivity index data array has a named component.
6340 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6341 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6342 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6344 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6347 int spaceDim=getSpaceDimension();
6348 int meshDim=getMeshDimension();
6349 if(spaceDim!=2 && spaceDim!=3)
6350 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6351 if(meshDim!=2 && meshDim!=3)
6352 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6353 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6355 int nbOfCells=getNumberOfCells();
6356 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6357 arr->alloc(nbOfCells,1);
6358 double *pt=arr->getPointer();
6359 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6360 const int *conn=_nodal_connec->getConstPointer();
6361 const int *connI=_nodal_connec_index->getConstPointer();
6362 const double *coo=_coords->getConstPointer();
6364 for(int i=0;i<nbOfCells;i++,pt++)
6366 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6369 case INTERP_KERNEL::NORM_TRI3:
6371 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6372 *pt=INTERP_KERNEL::triAspectRatio(tmp);
6375 case INTERP_KERNEL::NORM_QUAD4:
6377 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6378 *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6381 case INTERP_KERNEL::NORM_TETRA4:
6383 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6384 *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6388 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6390 conn+=connI[i+1]-connI[i];
6392 ret->setName("AspectRatio");
6393 ret->synchronizeTimeWithSupport();
6398 * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6399 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6400 * treated: INTERP_KERNEL::NORM_QUAD4.
6401 * For a cell of other type an exception is thrown.
6402 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6403 * cells and one time, lying on \a this mesh. The caller is to delete this
6404 * field using decrRef() as it is no more needed.
6405 * \throw If the coordinates array is not set.
6406 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6407 * \throw If the connectivity data array has more than one component.
6408 * \throw If the connectivity data array has a named component.
6409 * \throw If the connectivity index data array has more than one component.
6410 * \throw If the connectivity index data array has a named component.
6411 * \throw If \a this->getMeshDimension() != 2.
6412 * \throw If \a this->getSpaceDimension() != 3.
6413 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6415 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6418 int spaceDim=getSpaceDimension();
6419 int meshDim=getMeshDimension();
6421 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6423 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6424 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6426 int nbOfCells=getNumberOfCells();
6427 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6428 arr->alloc(nbOfCells,1);
6429 double *pt=arr->getPointer();
6430 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6431 const int *conn=_nodal_connec->getConstPointer();
6432 const int *connI=_nodal_connec_index->getConstPointer();
6433 const double *coo=_coords->getConstPointer();
6435 for(int i=0;i<nbOfCells;i++,pt++)
6437 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6440 case INTERP_KERNEL::NORM_QUAD4:
6442 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6443 *pt=INTERP_KERNEL::quadWarp(tmp);
6447 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6449 conn+=connI[i+1]-connI[i];
6451 ret->setName("Warp");
6452 ret->synchronizeTimeWithSupport();
6458 * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6459 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6460 * treated: INTERP_KERNEL::NORM_QUAD4.
6461 * For a cell of other type an exception is thrown.
6462 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6463 * cells and one time, lying on \a this mesh. The caller is to delete this
6464 * field using decrRef() as it is no more needed.
6465 * \throw If the coordinates array is not set.
6466 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6467 * \throw If the connectivity data array has more than one component.
6468 * \throw If the connectivity data array has a named component.
6469 * \throw If the connectivity index data array has more than one component.
6470 * \throw If the connectivity index data array has a named component.
6471 * \throw If \a this->getMeshDimension() != 2.
6472 * \throw If \a this->getSpaceDimension() != 3.
6473 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6475 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6478 int spaceDim=getSpaceDimension();
6479 int meshDim=getMeshDimension();
6481 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6483 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6484 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6486 int nbOfCells=getNumberOfCells();
6487 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6488 arr->alloc(nbOfCells,1);
6489 double *pt=arr->getPointer();
6490 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6491 const int *conn=_nodal_connec->getConstPointer();
6492 const int *connI=_nodal_connec_index->getConstPointer();
6493 const double *coo=_coords->getConstPointer();
6495 for(int i=0;i<nbOfCells;i++,pt++)
6497 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6500 case INTERP_KERNEL::NORM_QUAD4:
6502 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6503 *pt=INTERP_KERNEL::quadSkew(tmp);
6507 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6509 conn+=connI[i+1]-connI[i];
6511 ret->setName("Skew");
6512 ret->synchronizeTimeWithSupport();
6517 * This method aggregate the bbox of each cell and put it into bbox parameter.
6519 * \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)
6520 * For all other cases this input parameter is ignored.
6521 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6523 * \throw If \a this is not fully set (coordinates and connectivity).
6524 * \throw If a cell in \a this has no valid nodeId.
6525 * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6527 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6529 int mDim(getMeshDimension()),sDim(getSpaceDimension());
6530 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.
6531 return getBoundingBoxForBBTreeFast();
6532 if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6534 bool presenceOfQuadratic(false);
6535 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6537 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6538 if(cm.isQuadratic())
6539 presenceOfQuadratic=true;
6541 if(!presenceOfQuadratic)
6542 return getBoundingBoxForBBTreeFast();
6543 if(mDim==2 && sDim==2)
6544 return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6546 return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6548 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) !");
6552 * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6553 * So meshes having quadratic cells the computed bounding boxes can be invalid !
6555 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6557 * \throw If \a this is not fully set (coordinates and connectivity).
6558 * \throw If a cell in \a this has no valid nodeId.
6560 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6562 checkFullyDefined();
6563 int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6564 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6565 double *bbox(ret->getPointer());
6566 for(int i=0;i<nbOfCells*spaceDim;i++)
6568 bbox[2*i]=std::numeric_limits<double>::max();
6569 bbox[2*i+1]=-std::numeric_limits<double>::max();
6571 const double *coordsPtr(_coords->getConstPointer());
6572 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6573 for(int i=0;i<nbOfCells;i++)
6575 int offset=connI[i]+1;
6576 int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6577 for(int j=0;j<nbOfNodesForCell;j++)
6579 int nodeId=conn[offset+j];
6580 if(nodeId>=0 && nodeId<nbOfNodes)
6582 for(int k=0;k<spaceDim;k++)
6584 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6585 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6592 std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6593 throw INTERP_KERNEL::Exception(oss.str().c_str());
6600 * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6601 * useful for 2D meshes having quadratic cells
6602 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6603 * the two extremities of the arc of circle).
6605 * \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)
6606 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6607 * \throw If \a this is not fully defined.
6608 * \throw If \a this is not a mesh with meshDimension equal to 2.
6609 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6610 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6612 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6614 checkFullyDefined();
6615 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6616 if(spaceDim!=2 || mDim!=2)
6617 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!");
6618 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6619 double *bbox(ret->getPointer());
6620 const double *coords(_coords->getConstPointer());
6621 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6622 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6624 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6625 int sz(connI[1]-connI[0]-1);
6626 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6627 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6628 INTERP_KERNEL::QuadraticPolygon *pol(0);
6629 for(int j=0;j<sz;j++)
6631 int nodeId(conn[*connI+1+j]);
6632 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6634 if(!cm.isQuadratic())
6635 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6637 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6638 INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6639 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax();
6645 * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6646 * useful for 2D meshes having quadratic cells
6647 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6648 * the two extremities of the arc of circle).
6650 * \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)
6651 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6652 * \throw If \a this is not fully defined.
6653 * \throw If \a this is not a mesh with meshDimension equal to 1.
6654 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6655 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6657 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6659 checkFullyDefined();
6660 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6661 if(spaceDim!=2 || mDim!=1)
6662 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!");
6663 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6664 double *bbox(ret->getPointer());
6665 const double *coords(_coords->getConstPointer());
6666 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6667 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6669 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6670 int sz(connI[1]-connI[0]-1);
6671 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6672 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6673 INTERP_KERNEL::Edge *edge(0);
6674 for(int j=0;j<sz;j++)
6676 int nodeId(conn[*connI+1+j]);
6677 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6679 if(!cm.isQuadratic())
6680 edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6682 edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6683 const INTERP_KERNEL::Bounds& b(edge->getBounds());
6684 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6691 namespace ParaMEDMEMImpl
6696 ConnReader(const int *c, int val):_conn(c),_val(val) { }
6697 bool operator() (const int& pos) { return _conn[pos]!=_val; }
6706 ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6707 bool operator() (const int& pos) { return _conn[pos]==_val; }
6717 * This method expects that \a this is sorted by types. If not an exception will be thrown.
6718 * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6719 * \a this is composed in cell types.
6720 * The returned array is of size 3*n where n is the number of different types present in \a this.
6721 * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here.
6722 * This parameter is kept only for compatibility with other methode listed above.
6724 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6726 checkConnectivityFullyDefined();
6727 const int *conn=_nodal_connec->getConstPointer();
6728 const int *connI=_nodal_connec_index->getConstPointer();
6729 const int *work=connI;
6730 int nbOfCells=getNumberOfCells();
6731 std::size_t n=getAllGeoTypes().size();
6732 std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6733 std::set<INTERP_KERNEL::NormalizedCellType> types;
6734 for(std::size_t i=0;work!=connI+nbOfCells;i++)
6736 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6737 if(types.find(typ)!=types.end())
6739 std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6740 oss << " is not contiguous !";
6741 throw INTERP_KERNEL::Exception(oss.str().c_str());
6745 const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6746 ret[3*i+1]=(int)std::distance(work,work2);
6753 * This method is used to check that this has contiguous cell type in same order than described in \a code.
6754 * only for types cell, type node is not managed.
6755 * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6756 * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6757 * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6758 * If 2 or more same geometric type is in \a code and exception is thrown too.
6760 * This method firstly checks
6761 * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6762 * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6763 * an exception is thrown too.
6765 * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6766 * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown
6767 * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6769 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6772 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6773 std::size_t sz=code.size();
6776 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6777 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6779 bool isNoPflUsed=true;
6780 for(std::size_t i=0;i<n;i++)
6781 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6783 types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6785 if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6786 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6787 isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6790 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6793 if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6794 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6795 if(types.size()==_types.size())
6798 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6800 int *retPtr=ret->getPointer();
6801 const int *connI=_nodal_connec_index->getConstPointer();
6802 const int *conn=_nodal_connec->getConstPointer();
6803 int nbOfCells=getNumberOfCells();
6806 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6808 i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6809 int offset=(int)std::distance(connI,i);
6810 const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6811 int nbOfCellsOfCurType=(int)std::distance(i,j);
6812 if(code[3*kk+2]==-1)
6813 for(int k=0;k<nbOfCellsOfCurType;k++)
6817 int idInIdsPerType=code[3*kk+2];
6818 if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6820 const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6823 zePfl->checkAllocated();
6824 if(zePfl->getNumberOfComponents()==1)
6826 for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6828 if(*k>=0 && *k<nbOfCellsOfCurType)
6829 *retPtr=(*k)+offset;
6832 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6833 oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6834 throw INTERP_KERNEL::Exception(oss.str().c_str());
6839 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6842 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6846 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6847 oss << " should be in [0," << idsPerType.size() << ") !";
6848 throw INTERP_KERNEL::Exception(oss.str().c_str());
6857 * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6858 * 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.
6859 * 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.
6860 * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6862 * \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.
6863 * \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,
6864 * \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6865 * \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.
6866 * This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6867 * \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
6869 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6872 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6873 if(profile->getNumberOfComponents()!=1)
6874 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6875 checkConnectivityFullyDefined();
6876 const int *conn=_nodal_connec->getConstPointer();
6877 const int *connI=_nodal_connec_index->getConstPointer();
6878 int nbOfCells=getNumberOfCells();
6879 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6880 std::vector<int> typeRangeVals(1);
6881 for(const int *i=connI;i!=connI+nbOfCells;)
6883 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6884 if(std::find(types.begin(),types.end(),curType)!=types.end())
6886 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6888 types.push_back(curType);
6889 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6890 typeRangeVals.push_back((int)std::distance(connI,i));
6893 DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6894 profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6895 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6896 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6897 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6899 int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6900 code.resize(3*nbOfCastsFinal);
6901 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6902 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6903 for(int i=0;i<nbOfCastsFinal;i++)
6905 int castId=castsPresent->getIJ(i,0);
6906 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6907 idsInPflPerType2.push_back(tmp3);
6908 code[3*i]=(int)types[castId];
6909 code[3*i+1]=tmp3->getNumberOfTuples();
6910 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6911 if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6913 tmp4->copyStringInfoFrom(*profile);
6914 idsPerType2.push_back(tmp4);
6915 code[3*i+2]=(int)idsPerType2.size()-1;
6922 std::size_t sz2=idsInPflPerType2.size();
6923 idsInPflPerType.resize(sz2);
6924 for(std::size_t i=0;i<sz2;i++)
6926 DataArrayInt *locDa=idsInPflPerType2[i];
6928 idsInPflPerType[i]=locDa;
6930 std::size_t sz=idsPerType2.size();
6931 idsPerType.resize(sz);
6932 for(std::size_t i=0;i<sz;i++)
6934 DataArrayInt *locDa=idsPerType2[i];
6936 idsPerType[i]=locDa;
6941 * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6942 * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6943 * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6944 * 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.
6946 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
6948 checkFullyDefined();
6949 nM1LevMesh->checkFullyDefined();
6950 if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6951 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6952 if(_coords!=nM1LevMesh->getCoords())
6953 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6954 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6955 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6956 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6957 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6958 desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6959 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6960 tmp->setConnectivity(tmp0,tmp1);
6961 tmp->renumberCells(ret0->getConstPointer(),false);
6962 revDesc=tmp->getNodalConnectivity();
6963 revDescIndx=tmp->getNodalConnectivityIndex();
6964 DataArrayInt *ret=0;
6965 if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6968 ret->getMaxValue(tmp2);
6970 std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6971 throw INTERP_KERNEL::Exception(oss.str().c_str());
6976 revDescIndx->incrRef();
6979 meshnM1Old2New=ret0;
6984 * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6985 * necessary for writing the mesh to MED file. Additionally returns a permutation array
6986 * in "Old to New" mode.
6987 * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6988 * this array using decrRef() as it is no more needed.
6989 * \throw If the nodal connectivity of cells is not defined.
6991 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
6993 checkConnectivityFullyDefined();
6994 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6995 renumberCells(ret->getConstPointer(),false);
7000 * This methods checks that cells are sorted by their types.
7001 * This method makes asumption (no check) that connectivity is correctly set before calling.
7003 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
7005 checkFullyDefined();
7006 const int *conn=_nodal_connec->getConstPointer();
7007 const int *connI=_nodal_connec_index->getConstPointer();
7008 int nbOfCells=getNumberOfCells();
7009 std::set<INTERP_KERNEL::NormalizedCellType> types;
7010 for(const int *i=connI;i!=connI+nbOfCells;)
7012 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7013 if(types.find(curType)!=types.end())
7015 types.insert(curType);
7016 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7022 * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
7023 * The geometric type order is specified by MED file.
7025 * \sa MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
7027 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
7029 return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7033 * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
7034 * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
7035 * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
7036 * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
7038 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7040 checkFullyDefined();
7041 const int *conn=_nodal_connec->getConstPointer();
7042 const int *connI=_nodal_connec_index->getConstPointer();
7043 int nbOfCells=getNumberOfCells();
7047 std::set<INTERP_KERNEL::NormalizedCellType> sg;
7048 for(const int *i=connI;i!=connI+nbOfCells;)
7050 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7051 const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
7052 if(isTypeExists!=orderEnd)
7054 int pos=(int)std::distance(orderBg,isTypeExists);
7058 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7062 if(sg.find(curType)==sg.end())
7064 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7075 * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
7076 * 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
7077 * 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'.
7079 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
7081 checkConnectivityFullyDefined();
7082 int nbOfCells=getNumberOfCells();
7083 const int *conn=_nodal_connec->getConstPointer();
7084 const int *connI=_nodal_connec_index->getConstPointer();
7085 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
7086 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
7087 tmpa->alloc(nbOfCells,1);
7088 tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
7089 tmpb->fillWithZero();
7090 int *tmp=tmpa->getPointer();
7091 int *tmp2=tmpb->getPointer();
7092 for(const int *i=connI;i!=connI+nbOfCells;i++)
7094 const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
7097 int pos=(int)std::distance(orderBg,where);
7099 tmp[std::distance(connI,i)]=pos;
7103 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
7104 std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
7105 oss << " has a type " << cm.getRepr() << " not in input array of type !";
7106 throw INTERP_KERNEL::Exception(oss.str().c_str());
7109 nbPerType=tmpb.retn();
7114 * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7116 * \return a new object containing the old to new correspondance.
7118 * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7120 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7122 return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7126 * 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.
7127 * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7128 * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7129 * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7131 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7133 DataArrayInt *nbPerType=0;
7134 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7135 nbPerType->decrRef();
7136 return tmpa->buildPermArrPerLevel();
7140 * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7141 * The number of cells remains unchanged after the call of this method.
7142 * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7143 * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7145 * \return the array giving the correspondance old to new.
7147 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7149 checkFullyDefined();
7151 const int *conn=_nodal_connec->getConstPointer();
7152 const int *connI=_nodal_connec_index->getConstPointer();
7153 int nbOfCells=getNumberOfCells();
7154 std::vector<INTERP_KERNEL::NormalizedCellType> types;
7155 for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7156 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7158 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7159 types.push_back(curType);
7160 for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7162 DataArrayInt *ret=DataArrayInt::New();
7163 ret->alloc(nbOfCells,1);
7164 int *retPtr=ret->getPointer();
7165 std::fill(retPtr,retPtr+nbOfCells,-1);
7167 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7169 for(const int *i=connI;i!=connI+nbOfCells;i++)
7170 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7171 retPtr[std::distance(connI,i)]=newCellId++;
7173 renumberCells(retPtr,false);
7178 * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7179 * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7180 * This method makes asumption that connectivity is correctly set before calling.
7182 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7184 checkConnectivityFullyDefined();
7185 const int *conn=_nodal_connec->getConstPointer();
7186 const int *connI=_nodal_connec_index->getConstPointer();
7187 int nbOfCells=getNumberOfCells();
7188 std::vector<MEDCouplingUMesh *> ret;
7189 for(const int *i=connI;i!=connI+nbOfCells;)
7191 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7192 int beginCellId=(int)std::distance(connI,i);
7193 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7194 int endCellId=(int)std::distance(connI,i);
7195 int sz=endCellId-beginCellId;
7196 int *cells=new int[sz];
7197 for(int j=0;j<sz;j++)
7198 cells[j]=beginCellId+j;
7199 MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7207 * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7208 * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7209 * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7211 * \return a newly allocated instance, that the caller must manage.
7212 * \throw If \a this contains more than one geometric type.
7213 * \throw If the nodal connectivity of \a this is not fully defined.
7214 * \throw If the internal data is not coherent.
7216 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7218 checkConnectivityFullyDefined();
7219 if(_types.size()!=1)
7220 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7221 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7222 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7223 ret->setCoords(getCoords());
7224 MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7227 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7228 retC->setNodalConnectivity(c);
7232 MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7234 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7235 DataArrayInt *c=0,*ci=0;
7236 convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7237 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7238 retD->setNodalConnectivity(cs,cis);
7243 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7245 checkConnectivityFullyDefined();
7246 if(_types.size()!=1)
7247 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7248 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7249 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7252 std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7253 oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7254 throw INTERP_KERNEL::Exception(oss.str().c_str());
7256 int nbCells=getNumberOfCells();
7258 int nbNodesPerCell=(int)cm.getNumberOfNodes();
7259 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7260 int *outPtr=connOut->getPointer();
7261 const int *conn=_nodal_connec->begin();
7262 const int *connI=_nodal_connec_index->begin();
7264 for(int i=0;i<nbCells;i++,connI++)
7266 if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7267 outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7270 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 << ") !";
7271 throw INTERP_KERNEL::Exception(oss.str().c_str());
7274 return connOut.retn();
7277 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7279 static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7280 checkConnectivityFullyDefined();
7281 if(_types.size()!=1)
7282 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7283 int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7285 throw INTERP_KERNEL::Exception(msg0);
7286 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7287 c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7288 int *cp(c->getPointer()),*cip(ci->getPointer());
7289 const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7291 for(int i=0;i<nbCells;i++,cip++,incip++)
7293 int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7294 int delta(stop-strt);
7297 if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7298 cp=std::copy(incp+strt,incp+stop,cp);
7300 throw INTERP_KERNEL::Exception(msg0);
7303 throw INTERP_KERNEL::Exception(msg0);
7304 cip[1]=cip[0]+delta;
7306 nodalConn=c.retn(); nodalConnIndex=ci.retn();
7310 * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7311 * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7312 * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7313 * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7314 * are not used here to avoid the build of big permutation array.
7316 * \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
7317 * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7318 * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7319 * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7320 * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7321 * output array gives for each chunck of same type the corresponding mesh id in \b ms.
7322 * \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
7323 * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7325 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7326 DataArrayInt *&szOfCellGrpOfSameType,
7327 DataArrayInt *&idInMsOfCellGrpOfSameType)
7329 std::vector<const MEDCouplingUMesh *> ms2;
7330 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7333 (*it)->checkConnectivityFullyDefined();
7337 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7338 const DataArrayDouble *refCoo=ms2[0]->getCoords();
7339 int meshDim=ms2[0]->getMeshDimension();
7340 std::vector<const MEDCouplingUMesh *> m1ssm;
7341 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7343 std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7344 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7346 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7347 ret1->alloc(0,1); ret2->alloc(0,1);
7348 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7350 if(meshDim!=(*it)->getMeshDimension())
7351 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7352 if(refCoo!=(*it)->getCoords())
7353 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7354 std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7355 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7356 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7357 for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7359 MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7360 m1ssmSingleAuto.push_back(singleCell);
7361 m1ssmSingle.push_back(singleCell);
7362 ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7365 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7366 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7367 std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7368 for(std::size_t i=0;i<m1ssm.size();i++)
7369 m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7370 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7371 szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7372 idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7377 * This method returns a newly created DataArrayInt instance.
7378 * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7380 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7382 checkFullyDefined();
7383 const int *conn=_nodal_connec->getConstPointer();
7384 const int *connIndex=_nodal_connec_index->getConstPointer();
7385 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7386 for(const int *w=begin;w!=end;w++)
7387 if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7388 ret->pushBackSilent(*w);
7393 * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7394 * are in [0:getNumberOfCells())
7396 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7398 checkFullyDefined();
7399 const int *conn=_nodal_connec->getConstPointer();
7400 const int *connI=_nodal_connec_index->getConstPointer();
7401 int nbOfCells=getNumberOfCells();
7402 std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7403 int *tmp=new int[nbOfCells];
7404 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7407 for(const int *i=connI;i!=connI+nbOfCells;i++)
7408 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7409 tmp[std::distance(connI,i)]=j++;
7411 DataArrayInt *ret=DataArrayInt::New();
7412 ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7413 ret->copyStringInfoFrom(*da);
7414 int *retPtr=ret->getPointer();
7415 const int *daPtr=da->getConstPointer();
7416 int nbOfElems=da->getNbOfElems();
7417 for(int k=0;k<nbOfElems;k++)
7418 retPtr[k]=tmp[daPtr[k]];
7424 * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7425 * This method \b works \b for mesh sorted by type.
7426 * cells whose ids is in 'idsPerGeoType' array.
7427 * This method conserves coords and name of mesh.
7429 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7431 std::vector<int> code=getDistributionOfTypes();
7432 std::size_t nOfTypesInThis=code.size()/3;
7433 int sz=0,szOfType=0;
7434 for(std::size_t i=0;i<nOfTypesInThis;i++)
7439 szOfType=code[3*i+1];
7441 for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7442 if(*work<0 || *work>=szOfType)
7444 std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7445 oss << ". It should be in [0," << szOfType << ") !";
7446 throw INTERP_KERNEL::Exception(oss.str().c_str());
7448 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7449 int *idsPtr=idsTokeep->getPointer();
7451 for(std::size_t i=0;i<nOfTypesInThis;i++)
7454 for(int j=0;j<code[3*i+1];j++)
7457 idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7458 offset+=code[3*i+1];
7460 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7461 ret->copyTinyInfoFrom(this);
7466 * This method returns a vector of size 'this->getNumberOfCells()'.
7467 * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7469 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7471 int ncell=getNumberOfCells();
7472 std::vector<bool> ret(ncell);
7473 const int *cI=getNodalConnectivityIndex()->getConstPointer();
7474 const int *c=getNodalConnectivity()->getConstPointer();
7475 for(int i=0;i<ncell;i++)
7477 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7478 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7479 ret[i]=cm.isQuadratic();
7485 * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7487 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7489 if(other->getType()!=UNSTRUCTURED)
7490 throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7491 const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7492 return MergeUMeshes(this,otherC);
7496 * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7497 * computed by averaging coordinates of cell nodes, so this method is not a right
7498 * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7499 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7500 * this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7501 * components. The caller is to delete this array using decrRef() as it is
7503 * \throw If the coordinates array is not set.
7504 * \throw If the nodal connectivity of cells is not defined.
7505 * \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7507 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7509 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7510 int spaceDim=getSpaceDimension();
7511 int nbOfCells=getNumberOfCells();
7512 ret->alloc(nbOfCells,spaceDim);
7513 ret->copyStringInfoFrom(*getCoords());
7514 double *ptToFill=ret->getPointer();
7515 const int *nodal=_nodal_connec->getConstPointer();
7516 const int *nodalI=_nodal_connec_index->getConstPointer();
7517 const double *coor=_coords->getConstPointer();
7518 for(int i=0;i<nbOfCells;i++)
7520 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7521 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7528 * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7529 * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the
7531 * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned
7532 * DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7534 * \sa MEDCouplingUMesh::getBarycenterAndOwner
7535 * \throw If \a this is not fully defined (coordinates and connectivity)
7536 * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7538 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7540 checkFullyDefined();
7541 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7542 int spaceDim=getSpaceDimension();
7543 int nbOfCells=getNumberOfCells();
7544 int nbOfNodes=getNumberOfNodes();
7545 ret->alloc(nbOfCells,spaceDim);
7546 double *ptToFill=ret->getPointer();
7547 const int *nodal=_nodal_connec->getConstPointer();
7548 const int *nodalI=_nodal_connec_index->getConstPointer();
7549 const double *coor=_coords->getConstPointer();
7550 for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7552 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7553 std::fill(ptToFill,ptToFill+spaceDim,0.);
7554 if(type!=INTERP_KERNEL::NORM_POLYHED)
7556 for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7558 if(*conn>=0 && *conn<nbOfNodes)
7559 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7562 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," << nbOfNodes << ") !";
7563 throw INTERP_KERNEL::Exception(oss.str().c_str());
7566 int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7567 if(nbOfNodesInCell>0)
7568 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7571 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7572 throw INTERP_KERNEL::Exception(oss.str().c_str());
7577 std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7579 for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7581 if(*it>=0 && *it<nbOfNodes)
7582 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7585 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," << nbOfNodes << ") !";
7586 throw INTERP_KERNEL::Exception(oss.str().c_str());
7590 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7593 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7594 throw INTERP_KERNEL::Exception(oss.str().c_str());
7602 * Returns a new DataArrayDouble holding barycenters of specified cells. The
7603 * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7604 * are specified via an array of cell ids.
7605 * \warning Validity of the specified cell ids is not checked!
7606 * Valid range is [ 0, \a this->getNumberOfCells() ).
7607 * \param [in] begin - an array of cell ids of interest.
7608 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7609 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7610 * end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7611 * caller is to delete this array using decrRef() as it is no more needed.
7612 * \throw If the coordinates array is not set.
7613 * \throw If the nodal connectivity of cells is not defined.
7615 * \if ENABLE_EXAMPLES
7616 * \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7617 * \ref py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7620 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7622 DataArrayDouble *ret=DataArrayDouble::New();
7623 int spaceDim=getSpaceDimension();
7624 int nbOfTuple=(int)std::distance(begin,end);
7625 ret->alloc(nbOfTuple,spaceDim);
7626 double *ptToFill=ret->getPointer();
7627 double *tmp=new double[spaceDim];
7628 const int *nodal=_nodal_connec->getConstPointer();
7629 const int *nodalI=_nodal_connec_index->getConstPointer();
7630 const double *coor=_coords->getConstPointer();
7631 for(const int *w=begin;w!=end;w++)
7633 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7634 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7642 * 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".
7643 * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7644 * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7645 * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7646 * This method is useful to detect 2D cells in 3D space that are not coplanar.
7648 * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7649 * \throw If spaceDim!=3 or meshDim!=2.
7650 * \throw If connectivity of \a this is invalid.
7651 * \throw If connectivity of a cell in \a this points to an invalid node.
7653 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7655 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7656 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7657 if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7658 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7659 ret->alloc(nbOfCells,4);
7660 double *retPtr(ret->getPointer());
7661 const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7662 const double *coor(_coords->begin());
7663 for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7665 double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7666 if(nodalI[1]-nodalI[0]>=3)
7668 for(int j=0;j<3;j++)
7670 int nodeId(nodal[nodalI[0]+1+j]);
7671 if(nodeId>=0 && nodeId<nbOfNodes)
7672 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7675 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7676 throw INTERP_KERNEL::Exception(oss.str().c_str());
7682 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7683 throw INTERP_KERNEL::Exception(oss.str().c_str());
7685 INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7686 retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7692 * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7695 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7698 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7699 da->checkAllocated();
7700 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7702 int nbOfTuples=da->getNumberOfTuples();
7703 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7704 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7705 c->alloc(2*nbOfTuples,1);
7706 cI->alloc(nbOfTuples+1,1);
7707 int *cp=c->getPointer();
7708 int *cip=cI->getPointer();
7710 for(int i=0;i<nbOfTuples;i++)
7712 *cp++=INTERP_KERNEL::NORM_POINT1;
7716 ret->setConnectivity(c,cI,true);
7720 * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7721 * Cells and nodes of
7722 * the first mesh precede cells and nodes of the second mesh within the result mesh.
7723 * \param [in] mesh1 - the first mesh.
7724 * \param [in] mesh2 - the second mesh.
7725 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7726 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7727 * is no more needed.
7728 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7729 * \throw If the coordinates array is not set in none of the meshes.
7730 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7731 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7733 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7735 std::vector<const MEDCouplingUMesh *> tmp(2);
7736 tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7737 return MergeUMeshes(tmp);
7741 * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7742 * Cells and nodes of
7743 * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7744 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7745 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7746 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7747 * is no more needed.
7748 * \throw If \a a.size() == 0.
7749 * \throw If \a a[ *i* ] == NULL.
7750 * \throw If the coordinates array is not set in none of the meshes.
7751 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7752 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7754 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7756 std::size_t sz=a.size();
7758 return MergeUMeshesLL(a);
7759 for(std::size_t ii=0;ii<sz;ii++)
7762 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7763 throw INTERP_KERNEL::Exception(oss.str().c_str());
7765 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7766 std::vector< const MEDCouplingUMesh * > aa(sz);
7768 for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7770 const MEDCouplingUMesh *cur=a[i];
7771 const DataArrayDouble *coo=cur->getCoords();
7773 spaceDim=coo->getNumberOfComponents();
7776 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7777 for(std::size_t i=0;i<sz;i++)
7779 bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7782 return MergeUMeshesLL(aa);
7787 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7790 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7791 std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7792 int meshDim=(*it)->getMeshDimension();
7793 int nbOfCells=(*it)->getNumberOfCells();
7794 int meshLgth=(*it++)->getMeshLength();
7795 for(;it!=a.end();it++)
7797 if(meshDim!=(*it)->getMeshDimension())
7798 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7799 nbOfCells+=(*it)->getNumberOfCells();
7800 meshLgth+=(*it)->getMeshLength();
7802 std::vector<const MEDCouplingPointSet *> aps(a.size());
7803 std::copy(a.begin(),a.end(),aps.begin());
7804 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7805 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7806 ret->setCoords(pts);
7807 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7808 c->alloc(meshLgth,1);
7809 int *cPtr=c->getPointer();
7810 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7811 cI->alloc(nbOfCells+1,1);
7812 int *cIPtr=cI->getPointer();
7816 for(it=a.begin();it!=a.end();it++)
7818 int curNbOfCell=(*it)->getNumberOfCells();
7819 const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7820 const int *curC=(*it)->_nodal_connec->getConstPointer();
7821 cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7822 for(int j=0;j<curNbOfCell;j++)
7824 const int *src=curC+curCI[j];
7826 for(;src!=curC+curCI[j+1];src++,cPtr++)
7834 offset+=curCI[curNbOfCell];
7835 offset2+=(*it)->getNumberOfNodes();
7838 ret->setConnectivity(c,cI,true);
7845 * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7846 * dimension and sharing the node coordinates array.
7847 * All cells of the first mesh precede all cells of the second mesh
7848 * within the result mesh.
7849 * \param [in] mesh1 - the first mesh.
7850 * \param [in] mesh2 - the second mesh.
7851 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7852 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7853 * is no more needed.
7854 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7855 * \throw If the meshes do not share the node coordinates array.
7856 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7857 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7859 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7861 std::vector<const MEDCouplingUMesh *> tmp(2);
7862 tmp[0]=mesh1; tmp[1]=mesh2;
7863 return MergeUMeshesOnSameCoords(tmp);
7867 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7868 * dimension and sharing the node coordinates array.
7869 * All cells of the *i*-th mesh precede all cells of the
7870 * (*i*+1)-th mesh within the result mesh.
7871 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7872 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7873 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7874 * is no more needed.
7875 * \throw If \a a.size() == 0.
7876 * \throw If \a a[ *i* ] == NULL.
7877 * \throw If the meshes do not share the node coordinates array.
7878 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7879 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7881 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7884 throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7885 for(std::size_t ii=0;ii<meshes.size();ii++)
7888 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7889 throw INTERP_KERNEL::Exception(oss.str().c_str());
7891 const DataArrayDouble *coords=meshes.front()->getCoords();
7892 int meshDim=meshes.front()->getMeshDimension();
7893 std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7895 int meshIndexLgth=0;
7896 for(;iter!=meshes.end();iter++)
7898 if(coords!=(*iter)->getCoords())
7899 throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7900 if(meshDim!=(*iter)->getMeshDimension())
7901 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7902 meshLgth+=(*iter)->getMeshLength();
7903 meshIndexLgth+=(*iter)->getNumberOfCells();
7905 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7906 nodal->alloc(meshLgth,1);
7907 int *nodalPtr=nodal->getPointer();
7908 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7909 nodalIndex->alloc(meshIndexLgth+1,1);
7910 int *nodalIndexPtr=nodalIndex->getPointer();
7912 for(iter=meshes.begin();iter!=meshes.end();iter++)
7914 const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7915 const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7916 int nbOfCells=(*iter)->getNumberOfCells();
7917 int meshLgth2=(*iter)->getMeshLength();
7918 nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7919 if(iter!=meshes.begin())
7920 nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7922 nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7925 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7926 ret->setName("merge");
7927 ret->setMeshDimension(meshDim);
7928 ret->setConnectivity(nodal,nodalIndex,true);
7929 ret->setCoords(coords);
7934 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7935 * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7936 * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7937 * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7938 * New" mode are returned for each input mesh.
7939 * \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7940 * \param [in] compType - specifies a cell comparison technique. For meaning of its
7941 * valid values [0,1,2], see zipConnectivityTraducer().
7942 * \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7943 * meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7944 * mesh. The caller is to delete each of the arrays using decrRef() as it is
7946 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7947 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7948 * is no more needed.
7949 * \throw If \a meshes.size() == 0.
7950 * \throw If \a meshes[ *i* ] == NULL.
7951 * \throw If the meshes do not share the node coordinates array.
7952 * \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7953 * \throw If the \a meshes are of different dimension (getMeshDimension()).
7954 * \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7955 * \throw If the nodal connectivity any of \a meshes includes an invalid id.
7957 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7959 //All checks are delegated to MergeUMeshesOnSameCoords
7960 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7961 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7962 corr.resize(meshes.size());
7963 std::size_t nbOfMeshes=meshes.size();
7965 const int *o2nPtr=o2n->getConstPointer();
7966 for(std::size_t i=0;i<nbOfMeshes;i++)
7968 DataArrayInt *tmp=DataArrayInt::New();
7969 int curNbOfCells=meshes[i]->getNumberOfCells();
7970 tmp->alloc(curNbOfCells,1);
7971 std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7972 offset+=curNbOfCells;
7973 tmp->setName(meshes[i]->getName());
7980 * Makes all given meshes share the nodal connectivity array. The common connectivity
7981 * array is created by concatenating the connectivity arrays of all given meshes. All
7982 * the given meshes must be of the same space dimension but dimension of cells **can
7983 * differ**. This method is particulary useful in MEDLoader context to build a \ref
7984 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7985 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7986 * \param [in,out] meshes - a vector of meshes to update.
7987 * \throw If any of \a meshes is NULL.
7988 * \throw If the coordinates array is not set in any of \a meshes.
7989 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7990 * \throw If \a meshes are of different space dimension.
7992 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
7994 std::size_t sz=meshes.size();
7997 std::vector< const DataArrayDouble * > coords(meshes.size());
7998 std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7999 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
8003 (*it)->checkConnectivityFullyDefined();
8004 const DataArrayDouble *coo=(*it)->getCoords();
8009 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8010 oss << " has no coordinate array defined !";
8011 throw INTERP_KERNEL::Exception(oss.str().c_str());
8016 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8017 oss << " is null !";
8018 throw INTERP_KERNEL::Exception(oss.str().c_str());
8021 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
8022 std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
8023 int offset=(*it)->getNumberOfNodes();
8024 (*it++)->setCoords(res);
8025 for(;it!=meshes.end();it++)
8027 int oldNumberOfNodes=(*it)->getNumberOfNodes();
8028 (*it)->setCoords(res);
8029 (*it)->shiftNodeNumbersInConn(offset);
8030 offset+=oldNumberOfNodes;
8035 * Merges nodes coincident with a given precision within all given meshes that share
8036 * the nodal connectivity array. The given meshes **can be of different** mesh
8037 * dimension. This method is particulary useful in MEDLoader context to build a \ref
8038 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8039 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8040 * \param [in,out] meshes - a vector of meshes to update.
8041 * \param [in] eps - the precision used to detect coincident nodes (infinite norm).
8042 * \throw If any of \a meshes is NULL.
8043 * \throw If the \a meshes do not share the same node coordinates array.
8044 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8046 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
8050 std::set<const DataArrayDouble *> s;
8051 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8054 s.insert((*it)->getCoords());
8057 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 !";
8058 throw INTERP_KERNEL::Exception(oss.str().c_str());
8063 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 !";
8064 throw INTERP_KERNEL::Exception(oss.str().c_str());
8066 const DataArrayDouble *coo=*(s.begin());
8070 DataArrayInt *comm,*commI;
8071 coo->findCommonTuples(eps,-1,comm,commI);
8072 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
8073 int oldNbOfNodes=coo->getNumberOfTuples();
8075 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
8076 if(oldNbOfNodes==newNbOfNodes)
8078 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
8079 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8081 (*it)->renumberNodesInConn(o2n->getConstPointer());
8082 (*it)->setCoords(newCoords);
8087 * 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.
8088 * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
8089 * \param isQuad specifies the policy of connectivity.
8090 * @ret in/out parameter in which the result will be append
8092 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
8094 INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
8095 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
8096 ret.push_back(cm.getExtrudedType());
8097 int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
8100 case INTERP_KERNEL::NORM_POINT1:
8102 ret.push_back(connBg[1]);
8103 ret.push_back(connBg[1]+nbOfNodesPerLev);
8106 case INTERP_KERNEL::NORM_SEG2:
8108 int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
8109 ret.insert(ret.end(),conn,conn+4);
8112 case INTERP_KERNEL::NORM_SEG3:
8114 int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8115 ret.insert(ret.end(),conn,conn+8);
8118 case INTERP_KERNEL::NORM_QUAD4:
8120 int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8121 ret.insert(ret.end(),conn,conn+8);
8124 case INTERP_KERNEL::NORM_TRI3:
8126 int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8127 ret.insert(ret.end(),conn,conn+6);
8130 case INTERP_KERNEL::NORM_TRI6:
8132 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,
8133 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8134 ret.insert(ret.end(),conn,conn+15);
8137 case INTERP_KERNEL::NORM_QUAD8:
8140 connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8141 connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8142 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8144 ret.insert(ret.end(),conn,conn+20);
8147 case INTERP_KERNEL::NORM_POLYGON:
8149 std::back_insert_iterator< std::vector<int> > ii(ret);
8150 std::copy(connBg+1,connEnd,ii);
8152 std::reverse_iterator<const int *> rConnBg(connEnd);
8153 std::reverse_iterator<const int *> rConnEnd(connBg+1);
8154 std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8155 std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8156 for(std::size_t i=0;i<nbOfRadFaces;i++)
8159 int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8160 std::copy(conn,conn+4,ii);
8165 throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8170 * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8172 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8175 double v[3]={0.,0.,0.};
8176 std::size_t sz=std::distance(begin,end);
8181 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];
8182 v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8183 v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8185 double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8187 // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8188 // SEG3 forming a circle):
8189 if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8191 v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8192 for(std::size_t j=0;j<sz;j++)
8194 if (j%2) // current point i is quadratic, next point i+1 is standard
8197 ip1 = (j+1)%sz; // ip1 = "i+1"
8199 else // current point i is standard, next point i+1 is quadratic
8204 v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8205 v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8206 v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8208 ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8214 * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8216 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8218 std::vector<std::pair<int,int> > edges;
8219 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8220 const int *bgFace=begin;
8221 for(std::size_t i=0;i<nbOfFaces;i++)
8223 const int *endFace=std::find(bgFace+1,end,-1);
8224 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8225 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8227 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8228 if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8230 edges.push_back(p1);
8234 return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8238 * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8240 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8242 double vec0[3],vec1[3];
8243 std::size_t sz=std::distance(begin,end);
8245 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8246 int nbOfNodes=(int)sz/2;
8247 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8248 const double *pt0=coords+3*begin[0];
8249 const double *pt1=coords+3*begin[nbOfNodes];
8250 vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8251 return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8254 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8256 std::size_t sz=std::distance(begin,end);
8257 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8258 std::size_t nbOfNodes(sz/2);
8259 std::copy(begin,end,(int *)tmp);
8260 for(std::size_t j=1;j<nbOfNodes;j++)
8262 begin[j]=tmp[nbOfNodes-j];
8263 begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8267 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8269 std::size_t sz=std::distance(begin,end);
8271 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8272 double vec0[3],vec1[3];
8273 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8274 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];
8275 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;
8278 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8280 std::size_t sz=std::distance(begin,end);
8282 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8284 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8285 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8286 return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8290 * 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 )
8291 * 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
8294 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8295 * \param [in] coords the coordinates with nb of components exactly equal to 3
8296 * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8297 * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8298 * \param [out] res the result is put at the end of the vector without any alteration of the data.
8300 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8302 int nbFaces=std::count(begin+1,end,-1)+1;
8303 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8304 double *vPtr=v->getPointer();
8305 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8306 double *pPtr=p->getPointer();
8307 const int *stFaceConn=begin+1;
8308 for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8310 const int *endFaceConn=std::find(stFaceConn,end,-1);
8311 ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8312 stFaceConn=endFaceConn+1;
8314 pPtr=p->getPointer(); vPtr=v->getPointer();
8315 DataArrayInt *comm1=0,*commI1=0;
8316 v->findCommonTuples(eps,-1,comm1,commI1);
8317 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8318 const int *comm1Ptr=comm1->getConstPointer();
8319 const int *commI1Ptr=commI1->getConstPointer();
8320 int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8321 res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8323 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8324 mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8325 mm->finishInsertingCells();
8327 for(int i=0;i<nbOfGrps1;i++)
8329 int vecId=comm1Ptr[commI1Ptr[i]];
8330 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8331 DataArrayInt *comm2=0,*commI2=0;
8332 tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8333 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8334 const int *comm2Ptr=comm2->getConstPointer();
8335 const int *commI2Ptr=commI2->getConstPointer();
8336 int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8337 for(int j=0;j<nbOfGrps2;j++)
8339 if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8341 res->insertAtTheEnd(begin,end);
8342 res->pushBackSilent(-1);
8346 int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8347 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8348 ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8349 DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8350 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8351 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8352 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8353 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8354 const int *idsNodePtr=idsNode->getConstPointer();
8355 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];
8356 double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8357 double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8358 if(std::abs(norm)>eps)
8360 double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8361 mm3->rotate(center,vec,angle);
8363 mm3->changeSpaceDimension(2);
8364 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8365 const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8366 const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8367 int nbOfCells=mm4->getNumberOfCells();
8368 for(int k=0;k<nbOfCells;k++)
8371 for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8372 res->pushBackSilent(idsNodePtr[*work]);
8373 res->pushBackSilent(-1);
8378 res->popBackSilent();
8382 * 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
8383 * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8385 * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8386 * \param [in] coords coordinates expected to have 3 components.
8387 * \param [in] begin start of the nodal connectivity of the face.
8388 * \param [in] end end of the nodal connectivity (excluded) of the face.
8389 * \param [out] v the normalized vector of size 3
8390 * \param [out] p the pos of plane
8392 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8394 std::size_t nbPoints=std::distance(begin,end);
8396 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8397 double vec[3]={0.,0.,0.};
8399 bool refFound=false;
8400 for(;j<nbPoints-1 && !refFound;j++)
8402 vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8403 vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8404 vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8405 double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8409 vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8412 for(std::size_t i=j;i<nbPoints-1;i++)
8415 curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8416 curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8417 curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8418 double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8421 curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8422 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];
8423 norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8426 v[0]/=norm; v[1]/=norm; v[2]/=norm;
8427 *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8431 throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8435 * This method tries to obtain a well oriented polyhedron.
8436 * If the algorithm fails, an exception will be thrown.
8438 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8440 std::list< std::pair<int,int> > edgesOK,edgesFinished;
8441 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8442 std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8444 int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8445 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8446 for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8448 while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8451 std::size_t smthChanged=0;
8452 for(std::size_t i=0;i<nbOfFaces;i++)
8454 endFace=std::find(bgFace+1,end,-1);
8455 nbOfEdgesInFace=std::distance(bgFace,endFace);
8459 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8461 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8462 std::pair<int,int> p2(p1.second,p1.first);
8463 bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8464 bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8465 if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8470 std::reverse(bgFace+1,endFace);
8471 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8473 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8474 std::pair<int,int> p2(p1.second,p1.first);
8475 if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8476 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8477 if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8478 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8479 std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8480 if(it!=edgesOK.end())
8483 edgesFinished.push_back(p1);
8486 edgesOK.push_back(p1);
8493 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8495 if(!edgesOK.empty())
8496 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8497 if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8498 {//not lucky ! The first face was not correctly oriented : reorient all faces...
8500 for(std::size_t i=0;i<nbOfFaces;i++)
8502 endFace=std::find(bgFace+1,end,-1);
8503 std::reverse(bgFace+1,endFace);
8509 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8511 int nbOfNodesExpected(skin->getNumberOfNodes());
8512 const int *n2oPtr(n2o->getConstPointer());
8513 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8514 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8515 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8516 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8517 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8518 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8519 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_POLYGON;
8520 if(nbOfNodesExpected<1)
8522 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8523 *work++=n2oPtr[prevNode];
8524 for(int i=1;i<nbOfNodesExpected;i++)
8526 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8528 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8529 conn.erase(prevNode);
8532 int curNode(*(conn.begin()));
8533 *work++=n2oPtr[curNode];
8534 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8535 shar.erase(prevCell);
8538 prevCell=*(shar.begin());
8542 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8545 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8548 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8553 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8555 int nbOfNodesExpected(skin->getNumberOfNodes());
8556 int nbOfTurn(nbOfNodesExpected/2);
8557 const int *n2oPtr(n2o->getConstPointer());
8558 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8559 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8560 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8561 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8562 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8563 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8564 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_QPOLYG;
8565 if(nbOfNodesExpected<1)
8567 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8568 *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8569 for(int i=1;i<nbOfTurn;i++)
8571 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8573 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8574 conn.erase(prevNode);
8577 int curNode(*(conn.begin()));
8578 *work=n2oPtr[curNode];
8579 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8580 shar.erase(prevCell);
8583 int curCell(*(shar.begin()));
8584 work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8590 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8593 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8596 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8602 * This method makes the assumption spacedimension == meshdimension == 2.
8603 * This method works only for linear cells.
8605 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8607 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8609 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8610 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8611 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8612 int oldNbOfNodes(skin->getNumberOfNodes());
8613 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8614 int nbOfNodesExpected(skin->getNumberOfNodes());
8615 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8616 int nbCells(skin->getNumberOfCells());
8617 if(nbCells==nbOfNodesExpected)
8618 return buildUnionOf2DMeshLinear(skin,n2o);
8619 else if(2*nbCells==nbOfNodesExpected)
8620 return buildUnionOf2DMeshQuadratic(skin,n2o);
8622 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8626 * This method makes the assumption spacedimension == meshdimension == 3.
8627 * This method works only for linear cells.
8629 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8631 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8633 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8634 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8635 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8636 const int *conn=m->getNodalConnectivity()->getConstPointer();
8637 const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8638 int nbOfCells=m->getNumberOfCells();
8639 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8640 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED;
8643 work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8644 for(int i=1;i<nbOfCells;i++)
8647 work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8653 * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8654 * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8656 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8660 for(int i=0;i<nbOfNodesInCell;i++)
8661 w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8662 else if(spaceDim==2)
8664 for(int i=0;i<nbOfNodesInCell;i++)
8666 w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8671 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8674 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8676 int nbOfCells=getNumberOfCells();
8678 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8679 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};
8680 ofs << " <" << getVTKDataSetType() << ">\n";
8681 ofs << " <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8682 ofs << " <PointData>\n" << pointData << std::endl;
8683 ofs << " </PointData>\n";
8684 ofs << " <CellData>\n" << cellData << std::endl;
8685 ofs << " </CellData>\n";
8686 ofs << " <Points>\n";
8687 if(getSpaceDimension()==3)
8688 _coords->writeVTK(ofs,8,"Points",byteData);
8691 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8692 coo->writeVTK(ofs,8,"Points",byteData);
8694 ofs << " </Points>\n";
8695 ofs << " <Cells>\n";
8696 const int *cPtr=_nodal_connec->getConstPointer();
8697 const int *cIPtr=_nodal_connec_index->getConstPointer();
8698 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8699 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8700 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8701 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8702 int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8703 int szFaceOffsets=0,szConn=0;
8704 for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8707 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8710 *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8711 w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8715 int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8716 *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8717 std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8718 *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8719 w4=std::copy(c.begin(),c.end(),w4);
8722 types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8723 types->writeVTK(ofs,8,"UInt8","types",byteData);
8724 offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8725 if(szFaceOffsets!=0)
8726 {//presence of Polyhedra
8727 connectivity->reAlloc(szConn);
8728 faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8729 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8730 w1=faces->getPointer();
8731 for(int i=0;i<nbOfCells;i++)
8732 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8734 int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8736 const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8737 for(int j=0;j<nbFaces;j++)
8739 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8740 *w1++=(int)std::distance(w6,w5);
8741 w1=std::copy(w6,w5,w1);
8745 faces->writeVTK(ofs,8,"Int32","faces",byteData);
8747 connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8748 ofs << " </Cells>\n";
8749 ofs << " </Piece>\n";
8750 ofs << " </" << getVTKDataSetType() << ">\n";
8753 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8755 stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8757 { stream << " Not set !"; return ; }
8758 stream << " Mesh dimension : " << _mesh_dim << ".";
8762 { stream << " No coordinates set !"; return ; }
8763 if(!_coords->isAllocated())
8764 { stream << " Coordinates set but not allocated !"; return ; }
8765 stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8766 stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8767 if(!_nodal_connec_index)
8768 { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8769 if(!_nodal_connec_index->isAllocated())
8770 { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8771 int lgth=_nodal_connec_index->getNumberOfTuples();
8772 int cpt=_nodal_connec_index->getNumberOfComponents();
8773 if(cpt!=1 || lgth<1)
8775 stream << std::endl << "Number of cells : " << lgth-1 << ".";
8778 std::string MEDCouplingUMesh::getVTKDataSetType() const
8780 return std::string("UnstructuredGrid");
8783 std::string MEDCouplingUMesh::getVTKFileExtension() const
8785 return std::string("vtu");
8789 * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8790 * returns a result mesh constituted by polygons.
8791 * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8792 * all nodes from m2.
8793 * The meshes should be in 2D space. In
8794 * addition, returns two arrays mapping cells of the result mesh to cells of the input
8796 * \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
8797 * 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)
8798 * \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
8799 * must be covered exactly by one entity, \b no \b more. If it is not the case, some tools are available to heal the mesh (conformize2D, mergeNodes)
8800 * \param [in] eps - precision used to detect coincident mesh entities.
8801 * \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8802 * cell an id of the cell of \a m1 it comes from. The caller is to delete
8803 * this array using decrRef() as it is no more needed.
8804 * \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8805 * cell an id of the cell of \a m2 it comes from. -1 value means that a
8806 * result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8807 * any cell of \a m2. The caller is to delete this array using decrRef() as
8808 * it is no more needed.
8809 * \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8810 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8811 * is no more needed.
8812 * \throw If the coordinates array is not set in any of the meshes.
8813 * \throw If the nodal connectivity of cells is not defined in any of the meshes.
8814 * \throw If any of the meshes is not a 2D mesh in 2D space.
8816 * \sa conformize2D, mergeNodes
8818 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8819 double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8822 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
8823 m1->checkFullyDefined();
8824 m2->checkFullyDefined();
8825 if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8826 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!");
8828 // Step 1: compute all edge intersections (new nodes)
8829 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8830 MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
8831 DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8832 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
8833 IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
8834 m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8835 addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
8836 revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8837 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8838 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8840 // Step 2: re-order newly created nodes according to the ordering found in m2
8841 std::vector< std::vector<int> > intersectEdge2;
8842 BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8843 subDiv2.clear(); dd5=0; dd6=0;
8846 std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8847 std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8848 BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8849 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8851 // Step 4: Prepare final result:
8852 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
8853 addCooDa->alloc((int)(addCoo.size())/2,2);
8854 std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8855 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
8856 addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8857 std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8858 std::vector<const DataArrayDouble *> coordss(4);
8859 coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8860 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
8861 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
8862 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8863 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8864 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8865 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8866 ret->setConnectivity(conn,connI,true);
8867 ret->setCoords(coo);
8868 cellNb1=c1.retn(); cellNb2=c2.retn();
8874 bool IsColinearOfACellOf(const std::vector< std::vector<int> >& intersectEdge1, const std::vector<int>& candidates, int start, int stop, int& retVal)
8876 if(candidates.empty())
8878 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
8880 const std::vector<int>& pool(intersectEdge1[*it]);
8881 int tmp[2]; tmp[0]=start; tmp[1]=stop;
8882 if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
8887 tmp[0]=stop; tmp[1]=start;
8888 if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
8897 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,
8898 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInRetColinear, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInMesh1DForIdsInRetColinear)
8900 idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1);
8901 idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1);
8902 int nCells(mesh1D->getNumberOfCells());
8903 if(nCells!=(int)intersectEdge2.size())
8904 throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
8905 const DataArrayDouble *coo2(mesh1D->getCoords());
8906 const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
8907 const double *coo2Ptr(coo2->begin());
8908 int offset1(coords1->getNumberOfTuples());
8909 int offset2(offset1+coo2->getNumberOfTuples());
8910 int offset3(offset2+addCoo.size()/2);
8911 std::vector<double> addCooQuad;
8912 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
8913 int tmp[4],cicnt(0),kk(0);
8914 for(int i=0;i<nCells;i++)
8916 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
8917 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
8918 const std::vector<int>& subEdges(intersectEdge2[i]);
8919 int nbSubEdge(subEdges.size()/2);
8920 for(int j=0;j<nbSubEdge;j++,kk++)
8922 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));
8923 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
8924 INTERP_KERNEL::Edge *e2Ptr(e2);
8925 std::map<int,int>::const_iterator itm;
8926 if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
8928 tmp[0]=INTERP_KERNEL::NORM_SEG3;
8929 itm=mergedNodes.find(subEdges[2*j]);
8930 tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
8931 itm=mergedNodes.find(subEdges[2*j+1]);
8932 tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
8933 tmp[3]=offset3+(int)addCooQuad.size()/2;
8935 e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2);
8937 cOut->insertAtTheEnd(tmp,tmp+4);
8938 ciOut->pushBackSilent(cicnt);
8942 tmp[0]=INTERP_KERNEL::NORM_SEG2;
8943 itm=mergedNodes.find(subEdges[2*j]);
8944 tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
8945 itm=mergedNodes.find(subEdges[2*j+1]);
8946 tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
8948 cOut->insertAtTheEnd(tmp,tmp+3);
8949 ciOut->pushBackSilent(cicnt);
8952 if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00))
8954 idsInRetColinear->pushBackSilent(kk);
8955 idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00);
8960 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
8961 ret->setConnectivity(cOut,ciOut,true);
8962 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr3(DataArrayDouble::New());
8963 arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
8964 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
8965 std::vector<const DataArrayDouble *> coordss(4);
8966 coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
8967 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
8968 ret->setCoords(arr);
8972 MEDCouplingUMesh *BuildRefined2DCellLinear(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
8974 std::vector<int> allEdges;
8975 for(const int *it2(descBg);it2!=descEnd;it2++)
8977 const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
8979 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
8981 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
8983 std::size_t nb(allEdges.size());
8985 throw INTERP_KERNEL::Exception("BuildRefined2DCellLinear : internal error 1 !");
8986 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
8987 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
8988 ret->setCoords(coords);
8989 ret->allocateCells(1);
8990 std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
8991 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
8992 connOut[kk]=allEdges[2*kk];
8993 ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]);
8997 MEDCouplingUMesh *BuildRefined2DCellQuadratic(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
8999 const int *c(mesh2D->getNodalConnectivity()->begin()),*ci(mesh2D->getNodalConnectivityIndex()->begin());
9000 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[cellIdInMesh2D]]));
9002 unsigned sz(cm.getNumberOfSons2(c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1));
9003 if(sz!=std::distance(descBg,descEnd))
9004 throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 1 !");
9005 INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]]);
9006 std::vector<int> allEdges,centers;
9007 const double *coordsPtr(coords->begin());
9008 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
9009 int offset(coords->getNumberOfTuples());
9010 for(const int *it2(descBg);it2!=descEnd;it2++,ii++)
9012 INTERP_KERNEL::NormalizedCellType typeOfSon;
9013 cm.fillSonCellNodalConnectivity2(ii,c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1,tmpPtr,typeOfSon);
9014 const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9016 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9018 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9020 centers.push_back(tmpPtr[2]);//special case where no subsplit of edge -> reuse the original center.
9022 {//the current edge has been subsplit -> create corresponding centers.
9023 std::size_t nbOfCentersToAppend(edge1.size()/2);
9024 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9025 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpPtr,coordsPtr,m));
9026 std::vector<int>::const_iterator it3(allEdges.end()-edge1.size());
9027 for(std::size_t k=0;k<nbOfCentersToAppend;k++)
9030 const double *aa(coordsPtr+2*(*it3++));
9031 const double *bb(coordsPtr+2*(*it3++));
9032 ee->getMiddleOfPoints(aa,bb,tmpp);
9033 addCoo->insertAtTheEnd(tmpp,tmpp+2);
9034 centers.push_back(offset+k);
9038 std::size_t nb(allEdges.size());
9040 throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 2 !");
9041 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9042 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9044 ret->setCoords(coords);
9047 addCoo->rearrange(2);
9048 addCoo=DataArrayDouble::Aggregate(coords,addCoo);
9049 ret->setCoords(addCoo);
9051 ret->allocateCells(1);
9052 std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9053 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9054 connOut[kk]=allEdges[2*kk];
9055 connOut.insert(connOut.end(),centers.begin(),centers.end());
9056 ret->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,connOut.size(),&connOut[0]);
9061 * This method creates a refinement of a cell in \a mesh2D. Those cell is defined by descending connectivity and the sorted subdivided nodal connectivity
9064 * \param [in] mesh2D - The origin 2D mesh. \b Warning \b coords are not those of \a mesh2D. But mesh2D->getCoords()==coords[:mesh2D->getNumberOfNodes()]
9066 MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9068 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(mesh2D->getTypeOfCell(cellIdInMesh2D)));
9069 if(!cm.isQuadratic())
9070 return BuildRefined2DCellLinear(coords,descBg,descEnd,intersectEdge1);
9072 return BuildRefined2DCellQuadratic(coords,mesh2D,cellIdInMesh2D,descBg,descEnd,intersectEdge1);
9075 void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector<int>& conn, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edges)
9078 for(std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >::const_iterator it=edges.begin();it!=edges.end();it++)
9080 const INTERP_KERNEL::Edge *ee(*it);
9081 if(dynamic_cast<const INTERP_KERNEL::EdgeArcCircle *>(ee))
9085 mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]);
9088 const double *coo(mesh2D->getCoords()->begin());
9089 std::size_t sz(conn.size());
9090 std::vector<double> addCoo;
9091 std::vector<int> conn2(conn);
9092 int offset(mesh2D->getNumberOfNodes());
9093 for(std::size_t i=0;i<sz;i++)
9096 edges[(i+1)%sz]->getMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);// tony a chier i+1 -> i
9097 addCoo.insert(addCoo.end(),tmp,tmp+2);
9098 conn2.push_back(offset+(int)i);
9100 mesh2D->getCoords()->rearrange(1);
9101 mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size());
9102 mesh2D->getCoords()->rearrange(2);
9103 mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]);
9108 * \b WARNING edges in out1 coming from \a splitMesh1D are \b NOT oriented because only used for equation of curve.
9110 * This method cuts in 2 parts the input 2D cell given using boundaries description (\a edge1Bis and \a edge1BisPtr) using
9111 * a set of edges defined in \a splitMesh1D.
9113 void BuildMesh2DCutInternal2(const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& edge1Bis, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edge1BisPtr,
9114 std::vector< std::vector<int> >& out0, std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& out1)
9116 std::size_t nb(edge1Bis.size()/2);
9117 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9118 int iEnd(splitMesh1D->getNumberOfCells());
9120 throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal2 : internal error ! input 1D mesh must have at least one cell !");
9122 const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9123 for(ii=0;ii<nb && edge1Bis[2*ii]!=cSplitPtr[ciSplitPtr[0]+1];ii++);
9124 for(jj=ii;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd-1]+2];jj++);
9127 {//the edges splitMesh1D[iStart:iEnd] does not fully cut the current 2D cell -> single output cell
9128 out0.resize(1); out1.resize(1);
9129 std::vector<int>& connOut(out0[0]);
9130 connOut.resize(nbOfEdgesOf2DCellSplit);
9131 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr(out1[0]);
9132 edgesPtr.resize(nbOfEdgesOf2DCellSplit);
9133 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9135 connOut[kk]=edge1Bis[2*kk];
9136 edgesPtr[kk]=edge1BisPtr[2*kk];
9141 // [i,iEnd[ contains the
9142 out0.resize(2); out1.resize(2);
9143 std::vector<int>& connOutLeft(out0[0]);
9144 std::vector<int>& connOutRight(out0[1]);//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1]
9145 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eleft(out1[0]);
9146 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eright(out1[1]);
9147 for(std::size_t k=ii;k<jj+1;k++)
9148 { connOutLeft.push_back(edge1Bis[2*k+1]); eleft.push_back(edge1BisPtr[2*k+1]); }
9149 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > ees(iEnd);
9150 for(int ik=0;ik<iEnd;ik++)
9152 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9153 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9156 for(int ik=iEnd-1;ik>=0;ik--)
9157 connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]);
9158 for(std::size_t k=jj+1;k<nbOfEdgesOf2DCellSplit+ii;k++)
9159 { connOutRight.push_back(edge1Bis[2*k+1]); eright.push_back(edge1BisPtr[2*k+1]); }
9160 eleft.insert(eleft.end(),ees.rbegin(),ees.rend());
9161 for(int ik=0;ik<iEnd;ik++)
9162 connOutRight.push_back(cSplitPtr[ciSplitPtr[ik]+2]);
9163 eright.insert(eright.end(),ees.begin(),ees.end());
9175 CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9177 std::vector<int> _edges;
9178 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > _edges_ptr;
9181 CellInfo::CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr)
9183 std::size_t nbe(edges.size());
9184 std::vector<int> edges2(2*nbe); std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edgesPtr2(2*nbe);
9185 for(std::size_t i=0;i<nbe;i++)
9187 edges2[2*i]=edges[i]; edges2[2*i+1]=edges[(i+1)%nbe];
9188 edgesPtr2[2*i]=edgesPtr[(i+1)%nbe]; edgesPtr2[2*i+1]=edgesPtr[(i+1)%nbe];//tony a chier
9190 _edges.resize(4*nbe); _edges_ptr.resize(4*nbe);
9191 std::copy(edges2.begin(),edges2.end(),_edges.begin()); std::copy(edges2.begin(),edges2.end(),_edges.begin()+2*nbe);
9192 std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()); std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()+2*nbe);
9198 EdgeInfo(int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh):_istart(istart),_iend(iend),_mesh(mesh),_left(-7),_right(-7) { }
9199 EdgeInfo(int istart, int iend, int pos, const MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge>& edge):_istart(istart),_iend(iend),_edge(edge),_left(pos),_right(pos+1) { }
9200 bool isInMyRange(int pos) const { return pos>=_istart && pos<_iend; }
9201 void somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9202 void feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const;
9206 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _mesh;
9207 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> _edge;
9212 void EdgeInfo::somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9214 const MEDCouplingUMesh *mesh(_mesh);
9220 { _left++; _right++; return ; }
9223 bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9224 if((isLeft && isRight) || (!isLeft && !isRight))
9225 throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 1 !");
9236 bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9237 if((isLeft && isRight) || (!isLeft && !isRight))
9238 throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 2 !");
9253 void EdgeInfo::feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const
9255 const MEDCouplingUMesh *mesh(_mesh);
9258 neighbors[0]=offset+_left; neighbors[1]=offset+_right;
9261 {// not fully splitting cell case
9262 if(mesh2D->getNumberOfCells()==1)
9263 {//little optimization. 1 cell no need to find in which cell mesh is !
9264 neighbors[0]=offset; neighbors[1]=offset;
9269 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9270 int cellId(mesh2D->getCellContainingPoint(barys->begin(),eps));
9272 throw INTERP_KERNEL::Exception("EdgeInfo::feedEdgeInfoAt : internal error !");
9273 neighbors[0]=offset+cellId; neighbors[1]=offset+cellId;
9278 class VectorOfCellInfo
9281 VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9282 std::size_t size() const { return _pool.size(); }
9283 int getPositionOf(double eps, const MEDCouplingUMesh *mesh) const;
9284 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);
9285 const std::vector<int>& getConnOf(int pos) const { return get(pos)._edges; }
9286 const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& getEdgePtrOf(int pos) const { return get(pos)._edges_ptr; }
9287 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> getZeMesh() const { return _ze_mesh; }
9288 void feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const;
9290 int getZePosOfEdgeGivenItsGlobalId(int pos) const;
9291 void updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9292 const CellInfo& get(int pos) const;
9293 CellInfo& get(int pos);
9295 std::vector<CellInfo> _pool;
9296 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _ze_mesh;
9297 std::vector<EdgeInfo> _edge_info;
9300 VectorOfCellInfo::VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr):_pool(1)
9302 _pool[0]._edges=edges;
9303 _pool[0]._edges_ptr=edgesPtr;
9306 int VectorOfCellInfo::getPositionOf(double eps, const MEDCouplingUMesh *mesh) const
9309 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : empty !");
9312 const MEDCouplingUMesh *zeMesh(_ze_mesh);
9314 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : null aggregated mesh !");
9315 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9316 return zeMesh->getCellContainingPoint(barys->begin(),eps);
9319 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)
9321 get(pos);//to check pos
9322 bool isFast(pos==0 && _pool.size()==1);
9323 std::size_t sz(edges.size());
9324 // dealing with edges
9326 _edge_info.push_back(EdgeInfo(istart,iend,mesh1DInCase));
9328 _edge_info.push_back(EdgeInfo(istart,iend,pos,edgePtrs[0].back()));
9330 std::vector<CellInfo> pool(_pool.size()-1+sz);
9331 for(int i=0;i<pos;i++)
9333 for(std::size_t j=0;j<sz;j++)
9334 pool[pos+j]=CellInfo(edges[j],edgePtrs[j]);
9335 for(int i=pos+1;i<(int)_pool.size();i++)
9336 pool[i+sz-1]=_pool[i];
9340 updateEdgeInfo(pos,edgePtrs[0],edgePtrs[1]);
9348 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > ms;
9351 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(0,pos,true)));
9355 if(pos<_ze_mesh->getNumberOfCells()-1)
9357 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(pos+1,_ze_mesh->getNumberOfCells(),true)));
9360 std::vector< const MEDCouplingUMesh *> ms2(ms.size());
9361 for(std::size_t j=0;j<ms2.size();j++)
9363 _ze_mesh=MEDCouplingUMesh::MergeUMeshesOnSameCoords(ms2);
9366 void VectorOfCellInfo::feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const
9368 _edge_info[getZePosOfEdgeGivenItsGlobalId(pos)].feedEdgeInfoAt(eps,_ze_mesh,offset,neighbors);
9371 int VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId(int pos) const
9374 throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id ! Must be >=0 !");
9376 for(std::vector<EdgeInfo>::const_iterator it=_edge_info.begin();it!=_edge_info.end();it++,ret++)
9378 if((*it).isInMyRange(pos))
9381 throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id !");
9384 void VectorOfCellInfo::updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9386 get(pos);//to check;
9387 if(_edge_info.empty())
9389 std::size_t sz(_edge_info.size()-1);
9390 for(std::size_t i=0;i<sz;i++)
9391 _edge_info[i].somethingHappendAt(pos,newLeft,newRight);
9394 const CellInfo& VectorOfCellInfo::get(int pos) const
9396 if(pos<0 || pos>=(int)_pool.size())
9397 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get const : invalid pos !");
9401 CellInfo& VectorOfCellInfo::get(int pos)
9403 if(pos<0 || pos>=(int)_pool.size())
9404 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get : invalid pos !");
9410 * - a \b closed set of edges ( \a allEdges and \a allEdgesPtr ) that defines the split descending 2D cell.
9411 * - \a splitMesh1D a split 2D curve mesh contained into 2D cell defined above.
9413 * This method returns the 2D mesh and feeds \a idsLeftRight using offset.
9415 * Algorithm : \a splitMesh1D is cut into contiguous parts. Each contiguous parts will build incrementally the output 2D cells.
9417 * \param [in] allEdges a list of pairs (beginNode, endNode). Linked with \a allEdgesPtr to get the equation of edge.
9419 MEDCouplingUMesh *BuildMesh2DCutInternal(double eps, const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& allEdges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& allEdgesPtr, int offset,
9420 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9422 int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells());
9423 if(nbCellsInSplitMesh1D==0)
9424 throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal : internal error ! input 1D mesh must have at least one cell !");
9425 const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9426 std::size_t nb(allEdges.size()),jj;
9428 throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !");
9429 std::vector<int> edge1Bis(nb*2);
9430 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edge1BisPtr(nb*2);
9431 std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin());
9432 std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb);
9433 std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin());
9434 std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb);
9436 idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(nbCellsInSplitMesh1D*2); idsLeftRight->fillWithValue(-2); idsLeftRight->rearrange(2);
9437 int *idsLeftRightPtr(idsLeftRight->getPointer());
9438 VectorOfCellInfo pool(edge1Bis,edge1BisPtr);
9439 for(int iStart=0;iStart<nbCellsInSplitMesh1D;)
9440 {// split [0:nbCellsInSplitMesh1D) in contiguous parts [iStart:iEnd)
9442 for(;iEnd<nbCellsInSplitMesh1D;)
9444 for(jj=0;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd]+2];jj++);
9450 if(iEnd<nbCellsInSplitMesh1D)
9453 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfSplitMesh1D(static_cast<MEDCouplingUMesh *>(splitMesh1D->buildPartOfMySelf2(iStart,iEnd,1,true)));
9454 int pos(pool.getPositionOf(eps,partOfSplitMesh1D));
9456 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>retTmp(MEDCouplingUMesh::New("",2));
9457 retTmp->setCoords(splitMesh1D->getCoords());
9458 retTmp->allocateCells();
9460 std::vector< std::vector<int> > out0;
9461 std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > > out1;
9463 BuildMesh2DCutInternal2(partOfSplitMesh1D,pool.getConnOf(pos),pool.getEdgePtrOf(pos),out0,out1);
9464 for(std::size_t cnt=0;cnt<out0.size();cnt++)
9465 AddCellInMesh2D(retTmp,out0[cnt],out1[cnt]);
9466 pool.setMeshAt(pos,retTmp,iStart,iEnd,partOfSplitMesh1D,out0,out1);
9470 for(int mm=0;mm<nbCellsInSplitMesh1D;mm++)
9471 pool.feedEdgeInfoAt(eps,mm,offset,idsLeftRightPtr+2*mm);
9472 return pool.getZeMesh().retn();
9475 MEDCouplingUMesh *BuildMesh2DCutFrom(double eps, int cellIdInMesh2D, const MEDCouplingUMesh *mesh2DDesc, const MEDCouplingUMesh *splitMesh1D,
9476 const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1, int offset,
9477 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9479 const int *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin());
9481 std::vector<int> allEdges;
9482 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > allEdgesPtr; // for each sub edge in splitMesh2D the uncut Edge object of the original mesh2D
9483 for(const int *it(descBg);it!=descEnd;it++) // for all edges in the descending connectivity of the 2D mesh in relative Fortran mode
9485 int edgeId(std::abs(*it)-1);
9486 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9487 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m));
9488 const std::vector<int>& edge1(intersectEdge1[edgeId]);
9490 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9492 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9493 std::size_t sz(edge1.size());
9494 for(std::size_t cnt=0;cnt<sz;cnt++)
9495 allEdgesPtr.push_back(ee);
9498 return BuildMesh2DCutInternal(eps,splitMesh1D,allEdges,allEdgesPtr,offset,idsLeftRight);
9501 bool AreEdgeEqual(const double *coo2D, const INTERP_KERNEL::CellModel& typ1, const int *conn1, const INTERP_KERNEL::CellModel& typ2, const int *conn2, double eps)
9503 if(!typ1.isQuadratic() && !typ2.isQuadratic())
9504 {//easy case comparison not
9505 return conn1[0]==conn2[0] && conn1[1]==conn2[1];
9507 else if(typ1.isQuadratic() && typ2.isQuadratic())
9509 bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9512 if(conn1[2]==conn2[2])
9514 const double *a(coo2D+2*conn1[2]),*b(coo2D+2*conn2[2]);
9515 double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9519 {//only one is quadratic
9520 bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9523 if(typ1.isQuadratic())
9525 const double *a(coo2D+2*conn1[2]),*bb(coo2D+2*conn2[0]),*be(coo2D+2*conn2[1]);
9526 double b[2]; b[0]=(be[0]+bb[0])/2.; b[1]=(be[1]+bb[1])/2.;
9527 double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9534 * This method returns among the cellIds [ \a candidatesIn2DBg , \a candidatesIn2DEnd ) in \a mesh2DSplit those exactly sharing \a cellIdInMesh1DSplitRelative in \a mesh1DSplit.
9535 * \a mesh2DSplit and \a mesh1DSplit are expected to share the coordinates array.
9537 * \param [in] cellIdInMesh1DSplitRelative is in Fortran mode using sign to specify direction.
9539 int FindRightCandidateAmong(const MEDCouplingUMesh *mesh2DSplit, const int *candidatesIn2DBg, const int *candidatesIn2DEnd, const MEDCouplingUMesh *mesh1DSplit, int cellIdInMesh1DSplitRelative, double eps)
9541 if(candidatesIn2DEnd==candidatesIn2DBg)
9542 throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 1 !");
9543 const double *coo(mesh2DSplit->getCoords()->begin());
9544 if(std::distance(candidatesIn2DBg,candidatesIn2DEnd)==1)
9545 return *candidatesIn2DBg;
9546 int edgeId(std::abs(cellIdInMesh1DSplitRelative)-1);
9547 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur1D(static_cast<MEDCouplingUMesh *>(mesh1DSplit->buildPartOfMySelf(&edgeId,&edgeId+1,true)));
9548 if(cellIdInMesh1DSplitRelative<0)
9549 cur1D->changeOrientationOfCells();
9550 const int *c1D(cur1D->getNodalConnectivity()->begin());
9551 const INTERP_KERNEL::CellModel& ref1DType(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c1D[0]));
9552 for(const int *it=candidatesIn2DBg;it!=candidatesIn2DEnd;it++)
9554 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur2D(static_cast<MEDCouplingUMesh *>(mesh2DSplit->buildPartOfMySelf(it,it+1,true)));
9555 const int *c(cur2D->getNodalConnectivity()->begin()),*ci(cur2D->getNodalConnectivityIndex()->begin());
9556 const INTERP_KERNEL::CellModel &cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[0]]));
9557 unsigned sz(cm.getNumberOfSons2(c+ci[0]+1,ci[1]-ci[0]-1));
9558 INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[1]-ci[0]]);
9559 for(unsigned it2=0;it2<sz;it2++)
9561 INTERP_KERNEL::NormalizedCellType typeOfSon;
9562 cm.fillSonCellNodalConnectivity2(it2,c+ci[0]+1,ci[1]-ci[0]-1,tmpPtr,typeOfSon);
9563 const INTERP_KERNEL::CellModel &curCM(INTERP_KERNEL::CellModel::GetCellModel(typeOfSon));
9564 if(AreEdgeEqual(coo,ref1DType,c1D+1,curCM,tmpPtr,eps))
9568 throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 2 ! Unable to find the edge among split cell !");
9574 * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
9575 * 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
9576 * and finaly, in case of quadratic polygon the centers of edges new nodes.
9577 * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
9579 * \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
9580 * 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)
9581 * \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
9582 * you can invoke orderConsecutiveCells1D on \a mesh1D.
9583 * \param [in] eps - precision used to perform intersections and localization operations.
9584 * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
9585 * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
9586 * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
9587 * 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.
9588 * \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
9589 * and the cell in \a splitMesh2D on the right for the 2nt component. -1 means no cell.
9590 * 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.
9592 * \sa Intersect2DMeshes, orderConsecutiveCells1D, conformize2D, mergeNodes
9594 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
9596 if(!mesh2D || !mesh1D)
9597 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
9598 mesh2D->checkFullyDefined();
9599 mesh1D->checkFullyDefined();
9600 const std::vector<std::string>& compNames(mesh2D->getCoords()->getInfoOnComponents());
9601 if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
9602 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
9603 // Step 1: compute all edge intersections (new nodes)
9604 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9605 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
9606 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9607 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9609 // Build desc connectivity
9610 DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
9611 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9612 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
9613 std::map<int,int> mergedNodes;
9614 Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes);
9615 // use mergeNodes to fix intersectEdge1
9616 for(std::vector< std::vector<int> >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++)
9618 std::size_t n((*it0).size()/2);
9619 int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]);
9620 std::map<int,int>::const_iterator it1;
9621 it1=mergedNodes.find(eltStart);
9622 if(it1!=mergedNodes.end())
9623 (*it0)[0]=(*it1).second;
9624 it1=mergedNodes.find(eltEnd);
9625 if(it1!=mergedNodes.end())
9626 (*it0)[2*n-1]=(*it1).second;
9629 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9630 addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9631 // Step 2: re-order newly created nodes according to the ordering found in m2
9632 std::vector< std::vector<int> > intersectEdge2;
9633 BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
9635 // Step 3: compute splitMesh1D
9636 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear;
9637 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2(DataArrayInt::New()); ret2->alloc(0,1);
9638 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1,
9639 idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear));
9640 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(std::numeric_limits<int>::max()); ret3->rearrange(2);
9641 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells()));
9642 // deal with cells in mesh2D that are not cut but only some of their edges are
9643 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCpy());
9644 idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1);
9645 idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique();
9646 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
9647 if(!idsInDesc2DToBeRefined->empty())
9649 DataArrayInt *out0(0),*outi0(0);
9650 MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
9651 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> outi0s(outi0);
9653 out0s=out0s->buildUnique();
9657 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1NonCol(static_cast<MEDCouplingUMesh *>(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end())));
9658 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> baryRet1(ret1NonCol->getBarycenterAndOwner());
9659 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elts,eltsIndex;
9660 mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
9661 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex2(eltsIndex->deltaShiftIndex());
9662 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex3(eltsIndex2->getIdsEqual(1));
9663 if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells())
9664 throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !");
9665 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToBeModified(elts->buildUnique());
9666 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells()));
9667 if((DataArrayInt *)out0s)
9668 untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one
9669 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > outMesh2DSplit;
9670 // OK all is ready to insert in ret2 mesh
9671 if(!untouchedCells->empty())
9672 {// the most easy part, cells in mesh2D not impacted at all
9673 outMesh2DSplit.push_back(static_cast<MEDCouplingUMesh *>(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end())));
9674 outMesh2DSplit.back()->setCoords(ret1->getCoords());
9675 ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end());
9677 if((DataArrayInt *)out0s)
9678 {// here dealing with cells in out0s but not in cellsToBeModified
9679 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fewModifiedCells(out0s->buildSubstraction(cellsToBeModified));
9680 const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin());
9681 for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++)
9683 outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),mesh2D,*it,dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1));
9684 ret1->setCoords(outMesh2DSplit.back()->getCoords());
9686 int offset(ret2->getNumberOfTuples());
9687 ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end());
9688 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1);
9689 partOfRet3->fillWithValue(std::numeric_limits<int>::max()); partOfRet3->rearrange(2);
9690 int kk(0),*ret3ptr(partOfRet3->getPointer());
9691 for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++)
9693 int faceId(std::abs(*it)-1);
9694 for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++)
9696 int tmp(fewModifiedCells->locateValue(*it2));
9699 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9700 ret3ptr[2*kk]=tmp+offset;
9701 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9702 ret3ptr[2*kk+1]=tmp+offset;
9705 {//the current edge is shared by a 2D cell that will be split just after
9706 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9707 ret3ptr[2*kk]=-(*it2+1);
9708 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9709 ret3ptr[2*kk+1]=-(*it2+1);
9713 m1Desc->setCoords(ret1->getCoords());
9714 ret1NonCol->setCoords(ret1->getCoords());
9715 ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true);
9716 if(!outMesh2DSplit.empty())
9718 DataArrayDouble *da(outMesh2DSplit.back()->getCoords());
9719 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> >::iterator itt=outMesh2DSplit.begin();itt!=outMesh2DSplit.end();itt++)
9720 (*itt)->setCoords(da);
9723 cellsToBeModified=cellsToBeModified->buildUniqueNotSorted();
9724 for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++)
9726 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell(elts->getIdsEqual(*it));
9727 idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end());
9728 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end()));
9729 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfMesh1CuttingCur2DCell(static_cast<MEDCouplingUMesh *>(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end())));
9730 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3;
9731 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));
9732 ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true);
9733 outMesh2DSplit.push_back(splitOfOneCell);
9734 for(int i=0;i<splitOfOneCell->getNumberOfCells();i++)
9735 ret2->pushBackSilent(*it);
9738 std::size_t nbOfMeshes(outMesh2DSplit.size());
9739 std::vector<const MEDCouplingUMesh *> tmp(nbOfMeshes);
9740 for(std::size_t i=0;i<nbOfMeshes;i++)
9741 tmp[i]=outMesh2DSplit[i];
9743 ret1->getCoords()->setInfoOnComponents(compNames);
9744 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2D(MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp));
9745 // To finish - filter ret3 - std::numeric_limits<int>::max() -> -1 - negate values must be resolved.
9747 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> edgesToDealWith(ret3->getIdsStrictlyNegative());
9748 for(const int *it=edgesToDealWith->begin();it!=edgesToDealWith->end();it++)
9750 int old2DCellId(-ret3->getIJ(*it,0)-1);
9751 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates(ret2->getIdsEqual(old2DCellId));
9752 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
9754 ret3->replaceOneValByInThis(std::numeric_limits<int>::max(),-1);
9757 splitMesh1D=ret1.retn();
9758 splitMesh2D=ret2D.retn();
9759 cellIdInMesh2D=ret2.retn();
9760 cellIdInMesh1D=ret3.retn();
9764 * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
9765 * (newly created) nodes corresponding to the edge intersections.
9767 * @param[out] cr, crI connectivity of the resulting mesh
9768 * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
9769 * TODO: describe input parameters
9771 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
9772 const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
9773 const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
9774 const std::vector<double>& addCoords,
9775 std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
9777 static const int SPACEDIM=2;
9778 const double *coo1(m1->getCoords()->getConstPointer());
9779 const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer());
9780 int offset1(m1->getNumberOfNodes());
9781 const double *coo2(m2->getCoords()->getConstPointer());
9782 const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer());
9783 int offset2(offset1+m2->getNumberOfNodes());
9784 int offset3(offset2+((int)addCoords.size())/2);
9785 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
9786 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9787 // Here a BBTree on 2D-cells, not on segments:
9788 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
9789 int ncell1(m1->getNumberOfCells());
9791 for(int i=0;i<ncell1;i++)
9793 std::vector<int> candidates2;
9794 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9795 std::map<INTERP_KERNEL::Node *,int> mapp;
9796 std::map<int,INTERP_KERNEL::Node *> mappRev;
9797 INTERP_KERNEL::QuadraticPolygon pol1;
9798 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
9799 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
9800 // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
9801 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
9802 // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
9803 pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
9804 desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
9806 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
9807 std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
9808 INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
9809 for(it1.first();!it1.finished();it1.next())
9810 edges1.insert(it1.current()->getPtr());
9812 std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
9813 std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
9815 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9817 INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
9818 const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
9819 // Complete mapping with elements coming from the current cell it2 in mesh2:
9820 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
9821 // pol2 is the new QP in the final merged result.
9822 pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
9823 pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
9826 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9828 INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
9829 pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
9830 //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
9831 pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9833 // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
9834 // by m2 but that we still want to keep in the final result.
9839 INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9841 catch(INTERP_KERNEL::Exception& e)
9843 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();
9844 throw INTERP_KERNEL::Exception(oss.str().c_str());
9847 for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
9848 (*it).second->decrRef();
9853 * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
9854 * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
9855 * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
9856 * The caller is to deal with the resulting DataArrayInt.
9857 * \throw If the coordinate array is not set.
9858 * \throw If the nodal connectivity of the cells is not defined.
9859 * \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
9860 * \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
9862 * \sa DataArrayInt::sortEachPairToMakeALinkedList
9864 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
9866 checkFullyDefined();
9867 if(getMeshDimension()!=1)
9868 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
9870 // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
9871 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
9872 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
9873 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
9874 const int *d(_d->getConstPointer()), *dI(_dI->getConstPointer());
9875 const int *rD(_rD->getConstPointer()), *rDI(_rDI->getConstPointer());
9876 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
9877 const int * dsi(_dsi->getConstPointer());
9878 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dsii = _dsi->getIdsNotInRange(0,3);
9880 if (dsii->getNumberOfTuples())
9881 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
9883 int nc(getNumberOfCells());
9884 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> result(DataArrayInt::New());
9885 result->alloc(nc,1);
9887 // set of edges not used so far
9888 std::set<int> edgeSet;
9889 for (int i=0; i<nc; edgeSet.insert(i), i++);
9893 // while we have points with only one neighbor segments
9896 std::list<int> linePiece;
9897 // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
9898 for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
9900 // Fill the list forward (resp. backward) from the start segment:
9901 int activeSeg = startSeg;
9902 int prevPointId = -20;
9904 while (!edgeSet.empty())
9906 if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
9909 linePiece.push_back(activeSeg);
9911 linePiece.push_front(activeSeg);
9912 edgeSet.erase(activeSeg);
9915 int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
9916 ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
9917 if (dsi[ptId] == 1) // hitting the end of the line
9920 int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
9921 activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
9924 // Done, save final piece into DA:
9925 std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
9926 newIdx += linePiece.size();
9928 // identify next valid start segment (one which is not consumed)
9929 if(!edgeSet.empty())
9930 startSeg = *(edgeSet.begin());
9932 while (!edgeSet.empty());
9933 return result.retn();
9938 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
9940 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> nTmp(n); nTmp->incrRef();
9941 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>::const_iterator it(m.find(nTmp));
9943 throw INTERP_KERNEL::Exception("Internal error in remapping !");
9944 int v((*it).second);
9945 if(v==forbVal0 || v==forbVal1)
9947 if(std::find(isect.begin(),isect.end(),v)==isect.end())
9951 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
9956 bool presenceOfOn(false);
9957 for(int i=0;i<sz;i++)
9959 INTERP_KERNEL::ElementaryEdge *e(c[i]);
9960 if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
9962 IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
9963 IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
9965 return presenceOfOn;
9971 * 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.
9972 * 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.
9973 * 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.
9974 * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to avoid to have a non conform mesh.
9976 * \return int - the number of new nodes created (in most of cases 0).
9978 * \throw If \a this is not coherent.
9979 * \throw If \a this has not spaceDim equal to 2.
9980 * \throw If \a this has not meshDim equal to 2.
9981 * \throw If some subcells needed to be split are orphan.
9982 * \sa MEDCouplingUMesh::conformize2D
9984 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
9986 if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
9987 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
9988 desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
9989 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
9990 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
9991 if(midOpt==0 && midOptI==0)
9993 split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
9996 else if(midOpt!=0 && midOptI!=0)
9997 return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
9999 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
10003 * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
10004 * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
10005 * 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
10006 * 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).
10007 * 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.
10009 * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
10010 * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
10012 * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
10013 * This method expects that all nodes in \a this are not closer than \a eps.
10014 * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
10016 * \param [in] eps the relative error to detect merged edges.
10017 * \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
10018 * that the user is expected to deal with.
10020 * \throw If \a this is not coherent.
10021 * \throw If \a this has not spaceDim equal to 2.
10022 * \throw If \a this has not meshDim equal to 2.
10023 * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
10025 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
10027 static const int SPACEDIM=2;
10029 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10030 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10031 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
10032 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
10033 const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
10034 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
10035 const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
10036 int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
10037 std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
10038 std::vector<double> addCoo;
10039 BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
10040 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10041 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10042 for(int i=0;i<nDescCell;i++)
10044 std::vector<int> candidates;
10045 myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
10046 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
10049 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10050 INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
10051 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
10052 INTERP_KERNEL::MergePoints merge;
10053 INTERP_KERNEL::QuadraticPolygon c1,c2;
10054 e1->intersectWith(e2,merge,c1,c2);
10055 e1->decrRef(); e2->decrRef();
10056 if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
10057 overlapEdge[i].push_back(*it);
10058 if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
10059 overlapEdge[*it].push_back(i);
10062 // splitting done. sort intersect point in intersectEdge.
10063 std::vector< std::vector<int> > middle(nDescCell);
10064 int nbOf2DCellsToBeSplit(0);
10065 bool middleNeedsToBeUsed(false);
10066 std::vector<bool> cells2DToTreat(nDescCell,false);
10067 for(int i=0;i<nDescCell;i++)
10069 std::vector<int>& isect(intersectEdge[i]);
10070 int sz((int)isect.size());
10073 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10074 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
10075 e->sortSubNodesAbs(coords,isect);
10080 int idx0(rdi[i]),idx1(rdi[i+1]);
10082 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
10083 if(!cells2DToTreat[rd[idx0]])
10085 cells2DToTreat[rd[idx0]]=true;
10086 nbOf2DCellsToBeSplit++;
10088 // try to reuse at most eventual 'middle' of SEG3
10089 std::vector<int>& mid(middle[i]);
10090 mid.resize(sz+1,-1);
10091 if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
10093 middleNeedsToBeUsed=true;
10094 const std::vector<int>& candidates(overlapEdge[i]);
10095 std::vector<int> trueCandidates;
10096 for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
10097 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
10098 trueCandidates.push_back(*itc);
10099 int stNode(c[ci[i]+1]),endNode(isect[0]);
10100 for(int j=0;j<sz+1;j++)
10102 for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
10104 int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
10105 if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
10106 { mid[j]=*itc; break; }
10109 endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
10114 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
10115 if(nbOf2DCellsToBeSplit==0)
10118 int *retPtr(ret->getPointer());
10119 for(int i=0;i<nCell;i++)
10120 if(cells2DToTreat[i])
10123 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
10124 DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
10125 MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
10126 DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
10127 if(middleNeedsToBeUsed)
10128 { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
10129 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
10130 int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
10131 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.
10132 setPartOfMySelf(ret->begin(),ret->end(),*modif);
10134 bool areNodesMerged; int newNbOfNodes;
10135 if(nbOfNodesCreated!=0)
10136 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
10142 * 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.
10143 * 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).
10144 * 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
10145 * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
10146 * 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
10147 * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
10149 * 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
10150 * using new instance, idem for coordinates.
10152 * 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.
10154 * \return DataArrayInt * - The list of cellIds in \a this that have at least one edge colinearized.
10156 * \throw If \a this is not coherent.
10157 * \throw If \a this has not spaceDim equal to 2.
10158 * \throw If \a this has not meshDim equal to 2.
10160 * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
10162 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
10164 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
10166 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10167 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10168 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10169 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10170 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
10171 const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
10172 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
10173 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
10174 const double *coords(_coords->begin());
10175 int *newciptr(newci->getPointer());
10176 for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
10178 if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
10179 ret->pushBackSilent(i);
10180 newciptr[1]=newc->getNumberOfTuples();
10185 if(!appendedCoords->empty())
10187 appendedCoords->rearrange(2);
10188 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
10190 setCoords(newCoords);
10193 setConnectivity(newc,newci,true);
10198 * \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.
10199 * 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.
10200 * And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
10201 * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
10202 * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
10203 * \param [out] addCoo - nodes to be append at the end
10204 * \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.
10206 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
10207 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)
10209 static const int SPACEDIM=2;
10210 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10211 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10212 const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer());
10213 // Build BB tree of all edges in the tool mesh (second mesh)
10214 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
10215 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10216 int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
10217 intersectEdge1.resize(nDescCell1);
10218 colinear2.resize(nDescCell2);
10219 subDiv2.resize(nDescCell2);
10220 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
10222 std::vector<int> candidates1(1);
10223 int offset1(m1Desc->getNumberOfNodes());
10224 int offset2(offset1+m2Desc->getNumberOfNodes());
10225 for(int i=0;i<nDescCell1;i++) // for all edges in the first mesh
10227 std::vector<int> candidates2; // edges of mesh2 candidate for intersection
10228 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10229 if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
10231 std::map<INTERP_KERNEL::Node *,int> map1,map2;
10232 // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
10233 INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
10235 INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
10236 // 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
10237 // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
10238 std::set<INTERP_KERNEL::Node *> nodes;
10239 pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
10240 std::size_t szz(nodes.size());
10241 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
10242 std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
10243 for(std::size_t iii=0;iii<szz;iii++,itt++)
10244 { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
10245 // end of protection
10246 // Performs egde cutting:
10247 pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes);
10252 // Copy the edge (take only the two first points, ie discard quadratic point at this stage)
10253 intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i]+3);
10258 * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
10259 * It builds the descending connectivity of the two meshes, and then using a binary tree
10260 * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
10261 * Documentation about parameters colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
10263 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
10264 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
10265 MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
10266 std::vector<double>& addCoo,
10267 MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
10269 // Build desc connectivity
10270 desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
10271 desc2=DataArrayInt::New();
10272 descIndx2=DataArrayInt::New();
10273 revDesc2=DataArrayInt::New();
10274 revDescIndx2=DataArrayInt::New();
10275 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
10276 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
10277 m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
10278 m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
10279 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
10280 std::map<int,int> notUsedMap;
10281 Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap);
10282 m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
10283 m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
10287 * This method performs the 2nd step of Partition of 2D mesh.
10288 * This method has 4 inputs :
10289 * - a mesh 'm1' with meshDim==1 and a SpaceDim==2
10290 * - a mesh 'm2' with meshDim==1 and a SpaceDim==2
10291 * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
10292 * 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'
10293 * Nodes end up lying consecutively on a cutted edge.
10294 * \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.
10295 * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
10296 * \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.
10297 * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
10298 * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
10300 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
10301 const std::vector<double>& addCoo,
10302 const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
10304 int offset1=m1->getNumberOfNodes();
10305 int ncell=m2->getNumberOfCells();
10306 const int *c=m2->getNodalConnectivity()->getConstPointer();
10307 const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
10308 const double *coo=m2->getCoords()->getConstPointer();
10309 const double *cooBis=m1->getCoords()->getConstPointer();
10310 int offset2=offset1+m2->getNumberOfNodes();
10311 intersectEdge.resize(ncell);
10312 for(int i=0;i<ncell;i++,cI++)
10314 const std::vector<int>& divs=subDiv[i];
10315 int nnode=cI[1]-cI[0]-1;
10316 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
10317 std::map<INTERP_KERNEL::Node *, int> mapp22;
10318 for(int j=0;j<nnode;j++)
10320 INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
10321 int nnid=c[(*cI)+j+1];
10322 mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
10323 mapp22[nn]=nnid+offset1;
10325 INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
10326 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
10327 ((*it).second.first)->decrRef();
10328 std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
10329 std::map<INTERP_KERNEL::Node *,int> mapp3;
10330 for(std::size_t j=0;j<divs.size();j++)
10333 INTERP_KERNEL::Node *tmp=0;
10335 tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
10336 else if(id<offset2)
10337 tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
10339 tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
10343 e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
10344 for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
10351 * 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).
10352 * 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
10353 * with a plane. The result will be put in 'cut3DSuf' out parameter.
10354 * \param [in] cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
10355 * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
10356 * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
10357 * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
10358 * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
10359 * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
10360 * \param [in] desc is the descending connectivity 3DSurf->3DCurve
10361 * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
10362 * \param [out] cut3DSuf input/output param.
10364 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
10365 const int *nodal3DCurve, const int *nodalIndx3DCurve,
10366 const int *desc, const int *descIndx,
10367 std::vector< std::pair<int,int> >& cut3DSurf)
10369 std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
10370 int nbOf3DSurfCell=(int)cut3DSurf.size();
10371 for(int i=0;i<nbOf3DSurfCell;i++)
10373 std::vector<int> res;
10374 int offset=descIndx[i];
10375 int nbOfSeg=descIndx[i+1]-offset;
10376 for(int j=0;j<nbOfSeg;j++)
10378 int edgeId=desc[offset+j];
10379 int status=cut3DCurve[edgeId];
10383 res.push_back(status);
10386 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
10387 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
10395 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10401 std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
10402 std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
10405 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10409 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
10414 {// case when plane is on a multi colinear edge of a polyhedron
10415 if((int)res.size()==2*nbOfSeg)
10417 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
10420 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
10427 * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
10428 * 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).
10429 * 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
10430 * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
10431 * \param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
10432 * \param desc is the descending connectivity 3D->3DSurf
10433 * \param descIndx is the descending connectivity index 3D->3DSurf
10435 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
10436 const int *desc, const int *descIndx,
10437 DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
10439 checkFullyDefined();
10440 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10441 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
10442 const int *nodal3D=_nodal_connec->getConstPointer();
10443 const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
10444 int nbOfCells=getNumberOfCells();
10445 for(int i=0;i<nbOfCells;i++)
10447 std::map<int, std::set<int> > m;
10448 int offset=descIndx[i];
10449 int nbOfFaces=descIndx[i+1]-offset;
10452 for(int j=0;j<nbOfFaces;j++)
10454 const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
10455 if(p.first!=-1 && p.second!=-1)
10459 start=p.first; end=p.second;
10460 m[p.first].insert(p.second);
10461 m[p.second].insert(p.first);
10465 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
10466 int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
10467 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
10468 INTERP_KERNEL::NormalizedCellType cmsId;
10469 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
10470 start=tmp[0]; end=tmp[nbOfNodesSon-1];
10471 for(unsigned k=0;k<nbOfNodesSon;k++)
10473 m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
10474 m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
10481 std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
10485 std::map<int, std::set<int> >::const_iterator it=m.find(start);
10486 const std::set<int>& s=(*it).second;
10487 std::set<int> s2; s2.insert(prev);
10489 std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
10492 int val=*s3.begin();
10493 conn.push_back(start);
10500 conn.push_back(end);
10503 nodalRes->insertAtTheEnd(conn.begin(),conn.end());
10504 nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
10505 cellIds->pushBackSilent(i);
10511 * 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
10512 * 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
10513 * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
10514 * 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
10515 * 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.
10517 * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
10519 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
10521 std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
10524 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
10525 if(cm.getDimension()==2)
10527 const int *node=nodalConnBg+1;
10528 int startNode=*node++;
10529 double refX=coords[2*startNode];
10530 for(;node!=nodalConnEnd;node++)
10532 if(coords[2*(*node)]<refX)
10535 refX=coords[2*startNode];
10538 std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
10542 double angle0=-M_PI/2;
10547 double angleNext=0.;
10548 while(nextNode!=startNode)
10552 for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
10554 if(*node!=tmpOut.back() && *node!=prevNode)
10556 tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
10557 double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
10562 res=angle0-angleM+2.*M_PI;
10571 if(nextNode!=startNode)
10573 angle0=angleNext-M_PI;
10576 prevNode=tmpOut.back();
10577 tmpOut.push_back(nextNode);
10580 std::vector<int> tmp3(2*(sz-1));
10581 std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
10582 std::copy(nodalConnBg+1,nodalConnEnd,it);
10583 if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
10585 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10588 if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
10590 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10595 nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
10596 nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
10601 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10604 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10608 * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
10609 * 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.
10611 * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
10612 * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
10613 * \param [in,out] arr array in which the remove operation will be done.
10614 * \param [in,out] arrIndx array in the remove operation will modify
10615 * \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])
10616 * \return true if \b arr and \b arrIndx have been modified, false if not.
10618 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
10620 if(!arrIndx || !arr)
10621 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
10622 if(offsetForRemoval<0)
10623 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
10624 std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
10625 int nbOfGrps=arrIndx->getNumberOfTuples()-1;
10626 int *arrIPtr=arrIndx->getPointer();
10628 int previousArrI=0;
10629 const int *arrPtr=arr->getConstPointer();
10630 std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
10631 for(int i=0;i<nbOfGrps;i++,arrIPtr++)
10633 if(*arrIPtr-previousArrI>offsetForRemoval)
10635 for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
10637 if(s.find(*work)==s.end())
10638 arrOut.push_back(*work);
10641 previousArrI=*arrIPtr;
10642 *arrIPtr=(int)arrOut.size();
10644 if(arr->getNumberOfTuples()==(int)arrOut.size())
10646 arr->alloc((int)arrOut.size(),1);
10647 std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
10652 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10653 * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
10654 * The selection of extraction is done standardly in new2old format.
10655 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10657 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10658 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10659 * \param [in] arrIn arr origin array from which the extraction will be done.
10660 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10661 * \param [out] arrOut the resulting array
10662 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10663 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
10665 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10666 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10668 if(!arrIn || !arrIndxIn)
10669 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
10670 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10671 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10672 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
10673 std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
10674 const int *arrInPtr=arrIn->getConstPointer();
10675 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10676 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10678 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10679 int maxSizeOfArr=arrIn->getNumberOfTuples();
10680 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10681 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10682 arrIo->alloc((int)(sz+1),1);
10683 const int *idsIt=idsOfSelectBg;
10684 int *work=arrIo->getPointer();
10687 for(std::size_t i=0;i<sz;i++,work++,idsIt++)
10689 if(*idsIt>=0 && *idsIt<nbOfGrps)
10690 lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
10693 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10694 throw INTERP_KERNEL::Exception(oss.str().c_str());
10700 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
10701 oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
10702 throw INTERP_KERNEL::Exception(oss.str().c_str());
10705 arro->alloc(lgth,1);
10706 work=arro->getPointer();
10707 idsIt=idsOfSelectBg;
10708 for(std::size_t i=0;i<sz;i++,idsIt++)
10710 if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
10711 work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
10714 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
10715 oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10716 throw INTERP_KERNEL::Exception(oss.str().c_str());
10719 arrOut=arro.retn();
10720 arrIndexOut=arrIo.retn();
10724 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10725 * 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 ).
10726 * The selection of extraction is done standardly in new2old format.
10727 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10729 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10730 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10731 * \param [in] arrIn arr origin array from which the extraction will be done.
10732 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10733 * \param [out] arrOut the resulting array
10734 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10735 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
10737 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10738 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10740 if(!arrIn || !arrIndxIn)
10741 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
10742 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10743 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10744 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
10745 int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
10746 const int *arrInPtr=arrIn->getConstPointer();
10747 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10748 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10750 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10751 int maxSizeOfArr=arrIn->getNumberOfTuples();
10752 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10753 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10754 arrIo->alloc((int)(sz+1),1);
10755 int idsIt=idsOfSelectStart;
10756 int *work=arrIo->getPointer();
10759 for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
10761 if(idsIt>=0 && idsIt<nbOfGrps)
10762 lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
10765 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10766 throw INTERP_KERNEL::Exception(oss.str().c_str());
10772 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
10773 oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
10774 throw INTERP_KERNEL::Exception(oss.str().c_str());
10777 arro->alloc(lgth,1);
10778 work=arro->getPointer();
10779 idsIt=idsOfSelectStart;
10780 for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
10782 if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
10783 work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
10786 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
10787 oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10788 throw INTERP_KERNEL::Exception(oss.str().c_str());
10791 arrOut=arro.retn();
10792 arrIndexOut=arrIo.retn();
10796 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10797 * 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
10798 * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
10799 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
10801 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10802 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10803 * \param [in] arrIn arr origin array from which the extraction will be done.
10804 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10805 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
10806 * \param [in] srcArrIndex index array of \b srcArr
10807 * \param [out] arrOut the resulting array
10808 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10810 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
10812 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10813 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
10814 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10816 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10817 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
10818 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10819 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10820 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10821 std::vector<bool> v(nbOfTuples,true);
10823 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10824 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10825 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10827 if(*it>=0 && *it<nbOfTuples)
10830 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
10834 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
10835 throw INTERP_KERNEL::Exception(oss.str().c_str());
10838 srcArrIndexPtr=srcArrIndex->getConstPointer();
10839 arrIo->alloc(nbOfTuples+1,1);
10840 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
10841 const int *arrInPtr=arrIn->getConstPointer();
10842 const int *srcArrPtr=srcArr->getConstPointer();
10843 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
10844 int *arroPtr=arro->getPointer();
10845 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
10849 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
10850 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
10854 std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
10855 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
10856 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
10859 arrOut=arro.retn();
10860 arrIndexOut=arrIo.retn();
10864 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10865 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
10867 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10868 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10869 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
10870 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10871 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
10872 * \param [in] srcArrIndex index array of \b srcArr
10874 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
10876 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
10877 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
10879 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10880 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
10881 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10882 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10883 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10884 int *arrInOutPtr=arrInOut->getPointer();
10885 const int *srcArrPtr=srcArr->getConstPointer();
10886 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10888 if(*it>=0 && *it<nbOfTuples)
10890 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
10891 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
10894 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] !";
10895 throw INTERP_KERNEL::Exception(oss.str().c_str());
10900 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
10901 throw INTERP_KERNEL::Exception(oss.str().c_str());
10907 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
10908 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
10909 * 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]].
10910 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
10911 * A negative value in \b arrIn means that it is ignored.
10912 * 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.
10914 * \param [in] arrIn arr origin array from which the extraction will be done.
10915 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10916 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
10917 * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
10919 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
10921 int seed=0,nbOfDepthPeelingPerformed=0;
10922 return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
10926 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
10927 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
10928 * 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]].
10929 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
10930 * A negative value in \b arrIn means that it is ignored.
10931 * 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.
10932 * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
10933 * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
10934 * \param [in] arrIn arr origin array from which the extraction will be done.
10935 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10936 * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
10937 * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
10938 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
10939 * \sa MEDCouplingUMesh::partitionBySpreadZone
10941 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
10943 nbOfDepthPeelingPerformed=0;
10945 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
10946 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10949 DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
10953 std::vector<bool> fetched(nbOfTuples,false);
10954 return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
10957 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
10959 nbOfDepthPeelingPerformed=0;
10960 if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
10961 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
10962 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10963 std::vector<bool> fetched2(nbOfTuples,false);
10965 for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
10967 if(*seedElt>=0 && *seedElt<nbOfTuples)
10968 { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
10970 { 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()); }
10972 const int *arrInPtr=arrIn->getConstPointer();
10973 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10974 int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
10975 std::vector<int> idsToFetch1(seedBg,seedEnd);
10976 std::vector<int> idsToFetch2;
10977 std::vector<int> *idsToFetch=&idsToFetch1;
10978 std::vector<int> *idsToFetchOther=&idsToFetch2;
10979 while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
10981 for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
10982 for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
10984 { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
10985 std::swap(idsToFetch,idsToFetchOther);
10986 idsToFetchOther->clear();
10987 nbOfDepthPeelingPerformed++;
10989 int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
10991 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
10992 int *retPtr=ret->getPointer();
10993 for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
11000 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11001 * 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
11002 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11003 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11005 * \param [in] start begin of set of ids of the input extraction (included)
11006 * \param [in] end end of set of ids of the input extraction (excluded)
11007 * \param [in] step step of the set of ids in range mode.
11008 * \param [in] arrIn arr origin array from which the extraction will be done.
11009 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11010 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11011 * \param [in] srcArrIndex index array of \b srcArr
11012 * \param [out] arrOut the resulting array
11013 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11015 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
11017 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11018 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11019 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11021 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11022 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
11023 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
11024 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
11025 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11027 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11028 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11029 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
11031 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11033 if(it>=0 && it<nbOfTuples)
11034 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
11037 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11038 throw INTERP_KERNEL::Exception(oss.str().c_str());
11041 srcArrIndexPtr=srcArrIndex->getConstPointer();
11042 arrIo->alloc(nbOfTuples+1,1);
11043 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11044 const int *arrInPtr=arrIn->getConstPointer();
11045 const int *srcArrPtr=srcArr->getConstPointer();
11046 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11047 int *arroPtr=arro->getPointer();
11048 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11050 int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
11053 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11054 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11058 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11059 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11062 arrOut=arro.retn();
11063 arrIndexOut=arrIo.retn();
11067 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11068 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11070 * \param [in] start begin of set of ids of the input extraction (included)
11071 * \param [in] end end of set of ids of the input extraction (excluded)
11072 * \param [in] step step of the set of ids in range mode.
11073 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11074 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11075 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11076 * \param [in] srcArrIndex index array of \b srcArr
11078 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11080 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11081 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11083 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11084 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
11085 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11086 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11087 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11088 int *arrInOutPtr=arrInOut->getPointer();
11089 const int *srcArrPtr=srcArr->getConstPointer();
11090 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
11092 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11094 if(it>=0 && it<nbOfTuples)
11096 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
11097 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
11100 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
11101 throw INTERP_KERNEL::Exception(oss.str().c_str());
11106 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11107 throw INTERP_KERNEL::Exception(oss.str().c_str());
11113 * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
11114 * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
11115 * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
11116 * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
11117 * The sum of measure field of returned mesh is equal to the sum of measure field of this.
11119 * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
11121 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
11123 checkFullyDefined();
11124 int mdim=getMeshDimension();
11125 int spaceDim=getSpaceDimension();
11127 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
11128 std::vector<DataArrayInt *> partition=partitionBySpreadZone();
11129 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
11130 std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
11131 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
11132 ret->setCoords(getCoords());
11133 ret->allocateCells((int)partition.size());
11135 for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
11137 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
11138 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
11142 cell=tmp->buildUnionOf2DMesh();
11145 cell=tmp->buildUnionOf3DMesh();
11148 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
11151 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
11154 ret->finishInsertingCells();
11159 * This method partitions \b this into contiguous zone.
11160 * This method only needs a well defined connectivity. Coordinates are not considered here.
11161 * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
11163 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
11165 int nbOfCellsCur=getNumberOfCells();
11166 std::vector<DataArrayInt *> ret;
11167 if(nbOfCellsCur<=0)
11169 DataArrayInt *neigh=0,*neighI=0;
11170 computeNeighborsOfCells(neigh,neighI);
11171 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
11172 std::vector<bool> fetchedCells(nbOfCellsCur,false);
11173 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
11175 while(seed<nbOfCellsCur)
11177 int nbOfPeelPerformed=0;
11178 ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
11179 seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
11181 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
11182 ret.push_back((*it).retn());
11187 * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
11188 * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
11190 * \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.
11191 * \return a newly allocated DataArrayInt to be managed by the caller.
11192 * \throw In case of \a code has not the right format (typically of size 3*n)
11194 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
11196 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
11197 std::size_t nb=code.size()/3;
11198 if(code.size()%3!=0)
11199 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
11200 ret->alloc((int)nb,2);
11201 int *retPtr=ret->getPointer();
11202 for(std::size_t i=0;i<nb;i++,retPtr+=2)
11204 retPtr[0]=code[3*i+2];
11205 retPtr[1]=code[3*i+2]+code[3*i+1];
11211 * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
11212 * All cells in \a this are expected to be linear 3D cells.
11213 * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
11214 * It leads to an increase to number of cells.
11215 * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
11216 * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints
11217 * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
11219 * \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.
11220 * For all other cells, the splitting policy will be ignored.
11221 * \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.
11222 * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
11223 * an id of old cell producing it. The caller is to delete this array using
11224 * decrRef() as it is no more needed.
11225 * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
11227 * \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
11228 * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
11230 * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
11231 * \throw If \a this is not fully constituted with linear 3D cells.
11232 * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
11234 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
11236 INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
11237 checkConnectivityFullyDefined();
11238 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
11239 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
11240 int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
11241 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
11242 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
11243 int *retPt(ret->getPointer());
11244 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
11245 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
11246 const int *oldc(_nodal_connec->begin());
11247 const int *oldci(_nodal_connec_index->begin());
11248 const double *coords(_coords->begin());
11249 for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
11251 std::vector<int> a; std::vector<double> b;
11252 INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
11253 std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
11254 const int *aa(&a[0]);
11257 for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
11259 *it=(-(*(it))-1+nbNodes);
11260 addPts->insertAtTheEnd(b.begin(),b.end());
11261 nbNodes+=(int)b.size()/3;
11263 for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
11264 newConn->insertAtTheEnd(aa,aa+4);
11266 if(!addPts->empty())
11268 addPts->rearrange(3);
11269 nbOfAdditionalPoints=addPts->getNumberOfTuples();
11270 addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
11271 ret0->setCoords(addPts);
11275 nbOfAdditionalPoints=0;
11276 ret0->setCoords(getCoords());
11278 ret0->setNodalConnectivity(newConn);
11280 ret->computeOffsets2();
11281 n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
11282 return ret0.retn();
11286 * 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).
11288 * \sa MEDCouplingUMesh::split2DCells
11290 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
11292 checkConnectivityFullyDefined();
11293 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
11294 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11295 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11296 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11297 int prevPosOfCi(ciPtr[0]);
11298 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11300 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
11301 *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
11302 for(int j=0;j<sz;j++)
11304 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
11305 for(int k=0;k<sz2;k++)
11306 *cPtr++=subPtr[offset2+k];
11308 *cPtr++=oldConn[prevPosOfCi+j+2];
11311 prevPosOfCi=ciPtr[1];
11312 ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11315 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
11316 _nodal_connec->decrRef();
11317 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
11320 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11326 int ret(nodesCnter++);
11328 e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
11329 addCoo.insertAtTheEnd(newPt,newPt+2);
11336 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)
11339 int trueStart(start>=0?start:nbOfEdges+start);
11340 tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
11341 newConnOfCell->insertAtTheEnd(tmp,tmp+3);
11346 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11347 InternalAddPoint(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
11348 middles.push_back(tmp3+offset);
11351 middles.push_back(connBg[trueStart+nbOfEdges]);
11355 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)
11357 int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
11358 newConnOfCell->pushBackSilent(tmpEnd);
11363 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11364 InternalAddPoint(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11365 middles.push_back(tmp3+offset);
11368 middles.push_back(connBg[start+nbOfEdges]);
11372 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)
11378 int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
11379 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11380 InternalAddPoint(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11381 middles.push_back(tmp3+offset);
11384 middles.push_back(connBg[start+nbOfEdges]);
11391 * 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 ) .
11392 * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
11394 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
11396 std::size_t sz(std::distance(connBg,connEnd));
11397 if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
11398 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
11400 INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
11401 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
11402 unsigned nbs(cm.getNumberOfSons2(connBg+1,sz)),nbOfHit(0);
11403 int posBaseElt(0),posEndElt(0),nbOfTurn(0);
11404 INTERP_KERNEL::NormalizedCellType typeOfSon;
11405 std::vector<int> middles;
11407 for(;nbOfHit<nbs;nbOfTurn++)
11409 cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
11410 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
11411 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11414 unsigned endI(nbs-nbOfHit);
11415 for(unsigned i=0;i<endI;i++)
11417 cm.fillSonCellNodalConnectivity2(posBaseElt+(int)i+1,connBg+1,sz,tmpConn,typeOfSon);
11418 INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11419 INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11420 bool isColinear(eint->areColinears());
11432 {//look if the first edge of cell is not colinear with last edges in this case the start of nodal connectivity is shifted back
11433 unsigned endII(nbs-nbOfHit-1);//warning nbOfHit can be modified, so put end condition in a variable.
11434 for(unsigned ii=0;ii<endII;ii++)
11436 cm.fillSonCellNodalConnectivity2(nbs-ii-1,connBg+1,sz,tmpConn,typeOfSon);
11437 eCand=MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m);
11438 eint=INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand);
11439 isColinear=eint->areColinears();
11455 //push [posBaseElt,posEndElt) in newConnOfCell using e
11457 EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11458 else if(nbOfHit!=nbs)
11459 EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11461 EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11462 posBaseElt=posEndElt;
11465 if(!middles.empty())
11466 newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
11471 * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
11473 * \return int - the number of new nodes created.
11474 * \sa MEDCouplingUMesh::split2DCells
11476 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
11479 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
11480 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11481 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
11482 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11483 const int *midPtr(mid->begin()),*midIPtr(midI->begin());
11484 const double *oldCoordsPtr(getCoords()->begin());
11485 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11486 int prevPosOfCi(ciPtr[0]);
11487 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11489 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
11490 for(int j=0;j<sz;j++)
11491 { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
11492 *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
11493 for(int j=0;j<sz;j++)//loop over subedges of oldConn
11495 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
11499 cPtr[1]=oldConn[prevPosOfCi+2+j];
11500 cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
11503 std::vector<INTERP_KERNEL::Node *> ns(3);
11504 ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
11505 ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
11506 ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
11507 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
11508 for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
11510 cPtr[1]=subPtr[offset2+k];
11511 cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
11513 int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
11515 { cPtr[1]=tmpEnd; }
11516 cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
11518 prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
11519 ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11522 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
11523 _nodal_connec->decrRef();
11524 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
11525 addCoo->rearrange(2);
11526 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
11528 return addCoo->getNumberOfTuples();
11531 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
11532 _own_cell(true),_cell_id(-1),_nb_cell(0)
11537 _nb_cell=mesh->getNumberOfCells();
11541 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
11549 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
11550 _own_cell(false),_cell_id(bg-1),
11557 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
11560 if(_cell_id<_nb_cell)
11569 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
11575 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
11577 return new MEDCouplingUMeshCellByTypeIterator(_mesh);
11580 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
11586 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
11594 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
11600 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
11605 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
11610 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
11612 return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
11615 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
11620 _nb_cell=mesh->getNumberOfCells();
11624 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
11631 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
11633 const int *c=_mesh->getNodalConnectivity()->getConstPointer();
11634 const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
11635 if(_cell_id<_nb_cell)
11637 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
11638 int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
11639 int startId=_cell_id;
11640 _cell_id+=nbOfElems;
11641 return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
11647 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
11651 _conn=mesh->getNodalConnectivity()->getPointer();
11652 _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
11656 void MEDCouplingUMeshCell::next()
11658 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11663 _conn_lgth=_conn_indx[1]-_conn_indx[0];
11666 std::string MEDCouplingUMeshCell::repr() const
11668 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11670 std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
11672 std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
11676 return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
11679 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
11681 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11682 return (INTERP_KERNEL::NormalizedCellType)_conn[0];
11684 return INTERP_KERNEL::NORM_ERROR;
11687 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
11690 if(_conn_lgth!=NOTICABLE_FIRST_VAL)