1 // Copyright (C) 2007-2015 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 // Author : Anthony Geay (CEA/DEN)
21 #include "MEDCouplingUMesh.hxx"
22 #include "MEDCoupling1GTUMesh.hxx"
23 #include "MEDCouplingMemArray.txx"
24 #include "MEDCouplingFieldDouble.hxx"
25 #include "CellModel.hxx"
26 #include "VolSurfUser.txx"
27 #include "InterpolationUtils.hxx"
28 #include "PointLocatorAlgos.txx"
30 #include "BBTreeDst.txx"
31 #include "SplitterTetra.hxx"
32 #include "DiameterCalculator.hxx"
33 #include "DirectedBoundingBox.hxx"
34 #include "InterpKernelMatrixTools.hxx"
35 #include "InterpKernelMeshQuality.hxx"
36 #include "InterpKernelCellSimplify.hxx"
37 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
38 #include "InterpKernelAutoPtr.hxx"
39 #include "InterpKernelGeo2DNode.hxx"
40 #include "InterpKernelGeo2DEdgeLin.hxx"
41 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
42 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
51 using namespace ParaMEDMEM;
53 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
55 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 };
57 MEDCouplingUMesh *MEDCouplingUMesh::New()
59 return new MEDCouplingUMesh;
62 MEDCouplingUMesh *MEDCouplingUMesh::New(const std::string& meshName, int meshDim)
64 MEDCouplingUMesh *ret=new MEDCouplingUMesh;
65 ret->setName(meshName);
66 ret->setMeshDimension(meshDim);
71 * Returns a new MEDCouplingMesh which is a full copy of \a this one. No data is shared
72 * between \a this and the new mesh.
73 * \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
74 * delete this mesh using decrRef() as it is no more needed.
76 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
82 * Returns a new MEDCouplingMesh which is a copy of \a this one.
83 * \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
84 * this mesh are shared by the new mesh.
85 * \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
86 * delete this mesh using decrRef() as it is no more needed.
88 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
90 return new MEDCouplingUMesh(*this,recDeepCpy);
94 * This method behaves mostly like MEDCouplingUMesh::deepCpy method, except that only nodal connectivity arrays are deeply copied.
95 * The coordinates are shared between \a this and the returned instance.
97 * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
98 * \sa MEDCouplingUMesh::deepCpy
100 MEDCouplingPointSet *MEDCouplingUMesh::deepCpyConnectivityOnly() const
102 checkConnectivityFullyDefined();
103 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=clone(false);
104 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(getNodalConnectivity()->deepCpy()),ci(getNodalConnectivityIndex()->deepCpy());
105 ret->setConnectivity(c,ci);
109 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other)
112 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
113 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
115 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
116 MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
117 setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
120 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
122 std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
126 std::vector<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildrenWithNull() const
128 std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildrenWithNull());
129 ret.push_back(_nodal_connec);
130 ret.push_back(_nodal_connec_index);
134 void MEDCouplingUMesh::updateTime() const
136 MEDCouplingPointSet::updateTime();
139 updateTimeWith(*_nodal_connec);
141 if(_nodal_connec_index)
143 updateTimeWith(*_nodal_connec_index);
147 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
152 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
153 * then \a this mesh is most probably is writable, exchangeable and available for most
154 * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
155 * this method to check that all is in order with \a this mesh.
156 * \throw If the mesh dimension is not set.
157 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
158 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
159 * \throw If the connectivity data array has more than one component.
160 * \throw If the connectivity data array has a named component.
161 * \throw If the connectivity index data array has more than one component.
162 * \throw If the connectivity index data array has a named component.
164 void MEDCouplingUMesh::checkCoherency() const
167 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
169 MEDCouplingPointSet::checkCoherency();
170 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
172 if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
174 std::ostringstream message;
175 message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
176 throw INTERP_KERNEL::Exception(message.str().c_str());
181 if(_nodal_connec->getNumberOfComponents()!=1)
182 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
183 if(_nodal_connec->getInfoOnComponent(0)!="")
184 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
188 throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
189 if(_nodal_connec_index)
191 if(_nodal_connec_index->getNumberOfComponents()!=1)
192 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
193 if(_nodal_connec_index->getInfoOnComponent(0)!="")
194 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
198 throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
202 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
203 * then \a this mesh is most probably is writable, exchangeable and available for all
204 * algorithms. <br> In addition to the checks performed by checkCoherency(), this
205 * method thoroughly checks the nodal connectivity.
206 * \param [in] eps - a not used parameter.
207 * \throw If the mesh dimension is not set.
208 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
209 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
210 * \throw If the connectivity data array has more than one component.
211 * \throw If the connectivity data array has a named component.
212 * \throw If the connectivity index data array has more than one component.
213 * \throw If the connectivity index data array has a named component.
214 * \throw If number of nodes defining an element does not correspond to the type of element.
215 * \throw If the nodal connectivity includes an invalid node id.
217 void MEDCouplingUMesh::checkCoherency1(double eps) const
222 int meshDim=getMeshDimension();
223 int nbOfNodes=getNumberOfNodes();
224 int nbOfCells=getNumberOfCells();
225 const int *ptr=_nodal_connec->getConstPointer();
226 const int *ptrI=_nodal_connec_index->getConstPointer();
227 for(int i=0;i<nbOfCells;i++)
229 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
230 if((int)cm.getDimension()!=meshDim)
232 std::ostringstream oss;
233 oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
234 throw INTERP_KERNEL::Exception(oss.str().c_str());
236 int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
238 if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
240 std::ostringstream oss;
241 oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " << cm.getNumberOfNodes();
242 oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
243 throw INTERP_KERNEL::Exception(oss.str().c_str());
245 if(cm.isQuadratic() && cm.isDynamic() && meshDim == 2)
246 if (nbOfNodesInCell % 2 || nbOfNodesInCell < 4)
248 std::ostringstream oss;
249 oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with quadratic type '" << cm.getRepr() << "' has " << nbOfNodesInCell;
250 oss << " nodes. This should be even, and greater or equal than 4!! Looks very bad!";
251 throw INTERP_KERNEL::Exception(oss.str().c_str());
253 for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
258 if(nodeId>=nbOfNodes)
260 std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes in the mesh !";
261 throw INTERP_KERNEL::Exception(oss.str().c_str());
266 std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " in connectivity ! sounds bad !";
267 throw INTERP_KERNEL::Exception(oss.str().c_str());
271 if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
273 std::ostringstream oss; oss << "Cell #" << i << " is built with node #-1 in connectivity ! sounds bad !";
274 throw INTERP_KERNEL::Exception(oss.str().c_str());
283 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
284 * then \a this mesh is most probably is writable, exchangeable and available for all
285 * algorithms. <br> This method performs the same checks as checkCoherency1() does.
286 * \param [in] eps - a not used parameter.
287 * \throw If the mesh dimension is not set.
288 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
289 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
290 * \throw If the connectivity data array has more than one component.
291 * \throw If the connectivity data array has a named component.
292 * \throw If the connectivity index data array has more than one component.
293 * \throw If the connectivity index data array has a named component.
294 * \throw If number of nodes defining an element does not correspond to the type of element.
295 * \throw If the nodal connectivity includes an invalid node id.
297 void MEDCouplingUMesh::checkCoherency2(double eps) const
299 checkCoherency1(eps);
303 * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
304 * elements contained in the mesh. For more info on the mesh dimension see
305 * \ref MEDCouplingUMeshPage.
306 * \param [in] meshDim - a new mesh dimension.
307 * \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
309 void MEDCouplingUMesh::setMeshDimension(int meshDim)
311 if(meshDim<-1 || meshDim>3)
312 throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
318 * Allocates memory to store an estimation of the given number of cells. Closer is the estimation to the number of cells effectively inserted,
319 * less will be the needs to realloc. If the number of cells to be inserted is not known simply put 0 to this parameter.
320 * If a nodal connectivity previouly existed before the call of this method, it will be reset.
322 * \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
324 * \if ENABLE_EXAMPLES
325 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
326 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
329 void MEDCouplingUMesh::allocateCells(int nbOfCells)
332 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
333 if(_nodal_connec_index)
335 _nodal_connec_index->decrRef();
339 _nodal_connec->decrRef();
341 _nodal_connec_index=DataArrayInt::New();
342 _nodal_connec_index->reserve(nbOfCells+1);
343 _nodal_connec_index->pushBackSilent(0);
344 _nodal_connec=DataArrayInt::New();
345 _nodal_connec->reserve(2*nbOfCells);
351 * Appends a cell to the connectivity array. For deeper understanding what is
352 * happening see \ref MEDCouplingUMeshNodalConnectivity.
353 * \param [in] type - type of cell to add.
354 * \param [in] size - number of nodes constituting this cell.
355 * \param [in] nodalConnOfCell - the connectivity of the cell to add.
357 * \if ENABLE_EXAMPLES
358 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
359 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
362 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
364 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
365 if(_nodal_connec_index==0)
366 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
367 if((int)cm.getDimension()==_mesh_dim)
370 if(size!=(int)cm.getNumberOfNodes())
372 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
373 oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
374 throw INTERP_KERNEL::Exception(oss.str().c_str());
376 int idx=_nodal_connec_index->back();
378 _nodal_connec_index->pushBackSilent(val);
379 _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
384 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
385 oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
386 oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
387 throw INTERP_KERNEL::Exception(oss.str().c_str());
392 * Compacts data arrays to release unused memory. This method is to be called after
393 * finishing cell insertion using \a this->insertNextCell().
395 * \if ENABLE_EXAMPLES
396 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
397 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
400 void MEDCouplingUMesh::finishInsertingCells()
402 _nodal_connec->pack();
403 _nodal_connec_index->pack();
404 _nodal_connec->declareAsNew();
405 _nodal_connec_index->declareAsNew();
410 * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
411 * Useful for python users.
413 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
415 return new MEDCouplingUMeshCellIterator(this);
419 * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
420 * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
421 * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
422 * Useful for python users.
424 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
426 if(!checkConsecutiveCellTypes())
427 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
428 return new MEDCouplingUMeshCellByTypeEntry(this);
432 * Returns a set of all cell types available in \a this mesh.
433 * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
434 * \warning this method does not throw any exception even if \a this is not defined.
435 * \sa MEDCouplingUMesh::getAllGeoTypesSorted
437 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
443 * This method returns the sorted list of geometric types in \a this.
444 * 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
445 * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
447 * \throw if connectivity in \a this is not correctly defined.
449 * \sa MEDCouplingMesh::getAllGeoTypes
451 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
453 std::vector<INTERP_KERNEL::NormalizedCellType> ret;
454 checkConnectivityFullyDefined();
455 int nbOfCells(getNumberOfCells());
458 if(getMeshLength()<1)
459 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
460 const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
461 ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
462 for(int i=1;i<nbOfCells;i++,ci++)
463 if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
464 ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
469 * This method is a method that compares \a this and \a other.
470 * This method compares \b all attributes, even names and component names.
472 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
475 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
476 std::ostringstream oss; oss.precision(15);
477 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
480 reason="mesh given in input is not castable in MEDCouplingUMesh !";
483 if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
485 if(_mesh_dim!=otherC->_mesh_dim)
487 oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" << otherC->_mesh_dim;
491 if(_types!=otherC->_types)
493 oss << "umesh geometric type mismatch :\nThis geometric types are :";
494 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
495 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
496 oss << "\nOther geometric types are :";
497 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
498 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
502 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
503 if(_nodal_connec==0 || otherC->_nodal_connec==0)
505 reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
508 if(_nodal_connec!=otherC->_nodal_connec)
509 if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
511 reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
514 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
515 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
517 reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
520 if(_nodal_connec_index!=otherC->_nodal_connec_index)
521 if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
523 reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
530 * Checks if data arrays of this mesh (node coordinates, nodal
531 * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
533 * \param [in] other - the mesh to compare with.
534 * \param [in] prec - precision value used to compare node coordinates.
535 * \return bool - \a true if the two meshes are same.
537 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
539 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
542 if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
544 if(_mesh_dim!=otherC->_mesh_dim)
546 if(_types!=otherC->_types)
548 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
549 if(_nodal_connec==0 || otherC->_nodal_connec==0)
551 if(_nodal_connec!=otherC->_nodal_connec)
552 if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
554 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
555 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
557 if(_nodal_connec_index!=otherC->_nodal_connec_index)
558 if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
564 * Checks if \a this and \a other meshes are geometrically equivalent with high
565 * probability, else an exception is thrown. The meshes are considered equivalent if
566 * (1) meshes contain the same number of nodes and the same number of elements of the
567 * same types (2) three cells of the two meshes (first, last and middle) are based
568 * on coincident nodes (with a specified precision).
569 * \param [in] other - the mesh to compare with.
570 * \param [in] prec - the precision used to compare nodes of the two meshes.
571 * \throw If the two meshes do not match.
573 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
575 MEDCouplingPointSet::checkFastEquivalWith(other,prec);
576 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
578 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !");
582 * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
583 * cells each node belongs to.
584 * \warning For speed reasons, this method does not check if node ids in the nodal
585 * connectivity correspond to the size of node coordinates array.
586 * \param [in,out] revNodal - an array holding ids of cells sharing each node.
587 * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
588 * dividing cell ids in \a revNodal into groups each referring to one
589 * node. Its every element (except the last one) is an index pointing to the
590 * first id of a group of cells. For example cells sharing the node #1 are
591 * described by following range of indices:
592 * [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
593 * \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
594 * Number of cells sharing the *i*-th node is
595 * \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
596 * \throw If the coordinates array is not set.
597 * \throw If the nodal connectivity of cells is not defined.
599 * \if ENABLE_EXAMPLES
600 * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
601 * \ref py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
604 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
607 int nbOfNodes=getNumberOfNodes();
608 int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
609 revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
610 std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
611 const int *conn=_nodal_connec->getConstPointer();
612 const int *connIndex=_nodal_connec_index->getConstPointer();
613 int nbOfCells=getNumberOfCells();
614 int nbOfEltsInRevNodal=0;
615 for(int eltId=0;eltId<nbOfCells;eltId++)
617 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
618 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
619 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
620 if(*iter>=0)//for polyhedrons
622 nbOfEltsInRevNodal++;
623 revNodalIndxPtr[(*iter)+1]++;
626 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
627 int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
628 revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
629 std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
630 for(int eltId=0;eltId<nbOfCells;eltId++)
632 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
633 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
634 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
635 if(*iter>=0)//for polyhedrons
636 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
642 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
647 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
653 if(cm.getOrientationStatus(nb,conn1,conn2))
660 class MinusOneSonsGenerator
663 MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
664 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
665 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
666 static const int DELTA=1;
668 const INTERP_KERNEL::CellModel& _cm;
671 class MinusOneSonsGeneratorBiQuadratic
674 MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
675 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
676 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
677 static const int DELTA=1;
679 const INTERP_KERNEL::CellModel& _cm;
682 class MinusTwoSonsGenerator
685 MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
686 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
687 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
688 static const int DELTA=2;
690 const INTERP_KERNEL::CellModel& _cm;
696 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
697 * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
698 * describing correspondence between cells of \a this and the result meshes are
699 * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
700 * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
701 * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
702 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
703 * \warning For speed reasons, this method does not check if node ids in the nodal
704 * connectivity correspond to the size of node coordinates array.
705 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
706 * to write this mesh to the MED file, its cells must be sorted using
707 * sortCellsInMEDFileFrmt().
708 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
709 * each cell of \a this mesh.
710 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
711 * dividing cell ids in \a desc into groups each referring to one
712 * cell of \a this mesh. Its every element (except the last one) is an index
713 * pointing to the first id of a group of cells. For example cells of the
714 * result mesh bounding the cell #1 of \a this mesh are described by following
716 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
717 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
718 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
719 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
720 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
721 * by each cell of the result mesh.
722 * \param [in,out] revDescIndx - the array, of length one more than number of cells
723 * in the result mesh,
724 * dividing cell ids in \a revDesc into groups each referring to one
725 * cell of the result mesh the same way as \a descIndx divides \a desc.
726 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
727 * delete this mesh using decrRef() as it is no more needed.
728 * \throw If the coordinates array is not set.
729 * \throw If the nodal connectivity of cells is node defined.
730 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
731 * revDescIndx == NULL.
733 * \if ENABLE_EXAMPLES
734 * \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
735 * \ref py_mcumesh_buildDescendingConnectivity "Here is a Python example".
737 * \sa buildDescendingConnectivity2()
739 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
741 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
745 * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
746 * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
747 * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
748 * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
749 * \sa MEDCouplingUMesh::buildDescendingConnectivity
751 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
754 if(getMeshDimension()!=3)
755 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
756 return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
760 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
761 * this->getMeshDimension(), that bound cells of \a this mesh. In
762 * addition arrays describing correspondence between cells of \a this and the result
763 * meshes are returned. The arrays \a desc and \a descIndx describe the descending
764 * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
765 * mesh. This method differs from buildDescendingConnectivity() in that apart
766 * from cell ids, \a desc returns mutual orientation of cells in \a this and the
767 * result meshes. So a positive id means that order of nodes in corresponding cells
768 * of two meshes is same, and a negative id means a reverse order of nodes. Since a
769 * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
770 * i.e. cell ids are one-based.
771 * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
772 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
773 * \warning For speed reasons, this method does not check if node ids in the nodal
774 * connectivity correspond to the size of node coordinates array.
775 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
776 * to write this mesh to the MED file, its cells must be sorted using
777 * sortCellsInMEDFileFrmt().
778 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
779 * each cell of \a this mesh.
780 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
781 * dividing cell ids in \a desc into groups each referring to one
782 * cell of \a this mesh. Its every element (except the last one) is an index
783 * pointing to the first id of a group of cells. For example cells of the
784 * result mesh bounding the cell #1 of \a this mesh are described by following
786 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
787 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
788 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
789 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
790 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
791 * by each cell of the result mesh.
792 * \param [in,out] revDescIndx - the array, of length one more than number of cells
793 * in the result mesh,
794 * dividing cell ids in \a revDesc into groups each referring to one
795 * cell of the result mesh the same way as \a descIndx divides \a desc.
796 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
797 * shares the node coordinates array with \a this mesh. The caller is to
798 * delete this mesh using decrRef() as it is no more needed.
799 * \throw If the coordinates array is not set.
800 * \throw If the nodal connectivity of cells is node defined.
801 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
802 * revDescIndx == NULL.
804 * \if ENABLE_EXAMPLES
805 * \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
806 * \ref py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
808 * \sa buildDescendingConnectivity()
810 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
812 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
816 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
817 * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
818 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
819 * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
821 * \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
822 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
823 * \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.
825 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
827 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
828 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
829 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
830 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
831 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
833 ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
837 * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
838 * 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,
839 * excluding a set of meshdim-1 cells in input descending connectivity.
840 * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
841 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
842 * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
844 * \param [in] desc descending connectivity array.
845 * \param [in] descIndx descending connectivity index array used to walk through \b desc.
846 * \param [in] revDesc reverse descending connectivity array.
847 * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
848 * \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
849 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
850 * \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.
852 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
853 DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx)
855 if(!desc || !descIndx || !revDesc || !revDescIndx)
856 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
857 const int *descPtr=desc->getConstPointer();
858 const int *descIPtr=descIndx->getConstPointer();
859 const int *revDescPtr=revDesc->getConstPointer();
860 const int *revDescIPtr=revDescIndx->getConstPointer();
862 int nbCells=descIndx->getNumberOfTuples()-1;
863 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
864 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
865 int *out1Ptr=out1->getPointer();
867 out0->reserve(desc->getNumberOfTuples());
868 for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
870 for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
872 std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
874 out0->insertAtTheEnd(s.begin(),s.end());
876 *out1Ptr=out0->getNumberOfTuples();
878 neighbors=out0.retn();
879 neighborsIndx=out1.retn();
883 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
884 * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
885 * This method lists node by node in \b this which are its neighbors. To compute the result only connectivities are considered.
886 * The neighbor nodes of node having id 'nodeId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
888 * \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
889 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
890 * \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.
892 void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayInt *&neighbors, DataArrayInt *&neighborsIdx) const
895 int mdim(getMeshDimension()),nbNodes(getNumberOfNodes());
896 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descIndx(DataArrayInt::New()),revDesc(DataArrayInt::New()),revDescIndx(DataArrayInt::New());
897 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh1D;
902 mesh1D=explode3DMeshTo1D(desc,descIndx,revDesc,revDescIndx);
907 mesh1D=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
912 mesh1D=const_cast<MEDCouplingUMesh *>(this);
918 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2,1] !");
921 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=0; revDescIndx=0;
922 mesh1D->getReverseNodalConnectivity(desc,descIndx);
923 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0(DataArrayInt::New());
924 ret0->alloc(desc->getNumberOfTuples(),1);
925 int *r0Pt(ret0->getPointer());
926 const int *c1DPtr(mesh1D->getNodalConnectivity()->begin()),*rn(desc->begin()),*rni(descIndx->begin());
927 for(int i=0;i<nbNodes;i++,rni++)
929 for(const int *oneDCellIt=rn+rni[0];oneDCellIt!=rn+rni[1];oneDCellIt++)
930 *r0Pt++=c1DPtr[3*(*oneDCellIt)+1]==i?c1DPtr[3*(*oneDCellIt)+2]:c1DPtr[3*(*oneDCellIt)+1];
932 neighbors=ret0.retn();
933 neighborsIdx=descIndx.retn();
939 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
940 * For speed reasons no check of this will be done.
942 template<class SonsGenerator>
943 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
945 if(!desc || !descIndx || !revDesc || !revDescIndx)
946 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
947 checkConnectivityFullyDefined();
948 int nbOfCells=getNumberOfCells();
949 int nbOfNodes=getNumberOfNodes();
950 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
951 int *revNodalIndxPtr=revNodalIndx->getPointer();
952 const int *conn=_nodal_connec->getConstPointer();
953 const int *connIndex=_nodal_connec_index->getConstPointer();
954 std::string name="Mesh constituent of "; name+=getName();
955 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA);
956 ret->setCoords(getCoords());
957 ret->allocateCells(2*nbOfCells);
958 descIndx->alloc(nbOfCells+1,1);
959 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
960 int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
961 for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
963 int pos=connIndex[eltId];
964 int posP1=connIndex[eltId+1];
965 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
966 SonsGenerator sg(cm);
967 unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
968 INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
969 for(unsigned i=0;i<nbOfSons;i++)
971 INTERP_KERNEL::NormalizedCellType cmsId;
972 unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
973 for(unsigned k=0;k<nbOfNodesSon;k++)
975 revNodalIndxPtr[tmp[k]+1]++;
976 ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
977 revDesc2->pushBackSilent(eltId);
979 descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
981 int nbOfCellsM1=ret->getNumberOfCells();
982 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
983 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
984 std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
985 int *revNodalPtr=revNodal->getPointer();
986 const int *connM1=ret->getNodalConnectivity()->getConstPointer();
987 const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
988 for(int eltId=0;eltId<nbOfCellsM1;eltId++)
990 const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
991 const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
992 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
993 if(*iter>=0)//for polyhedrons
994 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
997 DataArrayInt *commonCells=0,*commonCellsI=0;
998 FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
999 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1000 const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
1001 int newNbOfCellsM1=-1;
1002 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
1003 commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
1004 std::vector<bool> isImpacted(nbOfCellsM1,false);
1005 for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
1006 for(int work2=work[0];work2!=work[1];work2++)
1007 isImpacted[commonCellsPtr[work2]]=true;
1008 const int *o2nM1Ptr=o2nM1->getConstPointer();
1009 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
1010 const int *n2oM1Ptr=n2oM1->getConstPointer();
1011 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
1012 ret2->copyTinyInfoFrom(this);
1013 desc->alloc(descIndx->back(),1);
1014 int *descPtr=desc->getPointer();
1015 const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
1016 for(int i=0;i<nbOfCellsM1;i++,descPtr++)
1019 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1022 if(i!=n2oM1Ptr[o2nM1Ptr[i]])
1024 const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
1025 *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
1028 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1031 revDesc->reserve(newNbOfCellsM1);
1032 revDescIndx->alloc(newNbOfCellsM1+1,1);
1033 int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
1034 const int *revDesc2Ptr=revDesc2->getConstPointer();
1035 for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
1037 int oldCellIdM1=n2oM1Ptr[i];
1038 if(!isImpacted[oldCellIdM1])
1040 revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
1041 revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
1045 for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
1046 revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
1047 revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
1055 struct MEDCouplingAccVisit
1057 MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1058 int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1059 int _new_nb_of_nodes;
1065 * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1066 * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1067 * array of cell ids. Pay attention that after conversion all algorithms work slower
1068 * with \a this mesh than before conversion. <br> If an exception is thrown during the
1069 * conversion due presence of invalid ids in the array of cells to convert, as a
1070 * result \a this mesh contains some already converted elements. In this case the 2D
1071 * mesh remains valid but 3D mesh becomes \b inconsistent!
1072 * \warning This method can significantly modify the order of geometric types in \a this,
1073 * hence, to write this mesh to the MED file, its cells must be sorted using
1074 * sortCellsInMEDFileFrmt().
1075 * \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1076 * \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1077 * cellIdsToConvertBg.
1078 * \throw If the coordinates array is not set.
1079 * \throw If the nodal connectivity of cells is node defined.
1080 * \throw If dimension of \a this mesh is not either 2 or 3.
1082 * \if ENABLE_EXAMPLES
1083 * \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1084 * \ref py_mcumesh_convertToPolyTypes "Here is a Python example".
1087 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1089 checkFullyDefined();
1090 int dim=getMeshDimension();
1092 throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1093 int nbOfCells(getNumberOfCells());
1096 const int *connIndex=_nodal_connec_index->getConstPointer();
1097 int *conn=_nodal_connec->getPointer();
1098 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1100 if(*iter>=0 && *iter<nbOfCells)
1102 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1103 if(!cm.isQuadratic())
1104 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1106 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1110 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1111 oss << " in range [0," << nbOfCells << ") !";
1112 throw INTERP_KERNEL::Exception(oss.str().c_str());
1118 int *connIndex(_nodal_connec_index->getPointer());
1119 const int *connOld(_nodal_connec->getConstPointer());
1120 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1121 std::vector<bool> toBeDone(nbOfCells,false);
1122 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1124 if(*iter>=0 && *iter<nbOfCells)
1125 toBeDone[*iter]=true;
1128 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1129 oss << " in range [0," << nbOfCells << ") !";
1130 throw INTERP_KERNEL::Exception(oss.str().c_str());
1133 for(int cellId=0;cellId<nbOfCells;cellId++)
1135 int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1136 int lgthOld(posP1-pos-1);
1137 if(toBeDone[cellId])
1139 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1140 unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1141 int *tmp(new int[nbOfFaces*lgthOld+1]);
1142 int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1143 for(unsigned j=0;j<nbOfFaces;j++)
1145 INTERP_KERNEL::NormalizedCellType type;
1146 unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1150 std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1151 connNew->pushBackValsSilent(tmp,tmp+newLgth);
1152 connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1157 connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1158 connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1161 setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1167 * Converts all cells to either polygons (if \a this is a 2D mesh) or
1168 * polyhedrons (if \a this is a 3D mesh).
1169 * \warning As this method is purely for user-friendliness and no optimization is
1170 * done to avoid construction of a useless vector, this method can be costly
1172 * \throw If the coordinates array is not set.
1173 * \throw If the nodal connectivity of cells is node defined.
1174 * \throw If dimension of \a this mesh is not either 2 or 3.
1176 void MEDCouplingUMesh::convertAllToPoly()
1178 int nbOfCells=getNumberOfCells();
1179 std::vector<int> cellIds(nbOfCells);
1180 for(int i=0;i<nbOfCells;i++)
1182 convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1186 * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1187 * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1188 * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1189 * base facet of the volume and the second half of nodes describes an opposite facet
1190 * having the same number of nodes as the base one. This method converts such
1191 * connectivity to a valid polyhedral format where connectivity of each facet is
1192 * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1193 * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1194 * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1195 * a correct orientation of the first facet of a polyhedron, else orientation of a
1196 * corrected cell is reverse.<br>
1197 * This method is useful to build an extruded unstructured mesh with polyhedrons as
1198 * it releases the user from boring description of polyhedra connectivity in the valid
1200 * \throw If \a this->getMeshDimension() != 3.
1201 * \throw If \a this->getSpaceDimension() != 3.
1202 * \throw If the nodal connectivity of cells is not defined.
1203 * \throw If the coordinates array is not set.
1204 * \throw If \a this mesh contains polyhedrons with the valid connectivity.
1205 * \throw If \a this mesh contains polyhedrons with odd number of nodes.
1207 * \if ENABLE_EXAMPLES
1208 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1209 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1212 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1214 checkFullyDefined();
1215 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1216 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1217 int nbOfCells=getNumberOfCells();
1218 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1219 newCi->alloc(nbOfCells+1,1);
1220 int *newci=newCi->getPointer();
1221 const int *ci=_nodal_connec_index->getConstPointer();
1222 const int *c=_nodal_connec->getConstPointer();
1224 for(int i=0;i<nbOfCells;i++)
1226 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1227 if(type==INTERP_KERNEL::NORM_POLYHED)
1229 if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1231 std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1232 throw INTERP_KERNEL::Exception(oss.str().c_str());
1234 std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1237 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 !";
1238 throw INTERP_KERNEL::Exception(oss.str().c_str());
1241 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)
1244 newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1246 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1247 newC->alloc(newci[nbOfCells],1);
1248 int *newc=newC->getPointer();
1249 for(int i=0;i<nbOfCells;i++)
1251 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1252 if(type==INTERP_KERNEL::NORM_POLYHED)
1254 std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1255 newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1257 for(std::size_t j=0;j<n1;j++)
1259 newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1261 newc[n1+5*j+1]=c[ci[i]+1+j];
1262 newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1263 newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1264 newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1269 newc=std::copy(c+ci[i],c+ci[i+1],newc);
1271 _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1272 _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1277 * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1278 * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1279 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1280 * to write this mesh to the MED file, its cells must be sorted using
1281 * sortCellsInMEDFileFrmt().
1282 * \return \c true if at least one cell has been converted, \c false else. In the
1283 * last case the nodal connectivity remains unchanged.
1284 * \throw If the coordinates array is not set.
1285 * \throw If the nodal connectivity of cells is not defined.
1286 * \throw If \a this->getMeshDimension() < 0.
1288 bool MEDCouplingUMesh::unPolyze()
1290 checkFullyDefined();
1291 int mdim=getMeshDimension();
1293 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1296 int nbOfCells=getNumberOfCells();
1299 int initMeshLgth=getMeshLength();
1300 int *conn=_nodal_connec->getPointer();
1301 int *index=_nodal_connec_index->getPointer();
1306 for(int i=0;i<nbOfCells;i++)
1308 lgthOfCurCell=index[i+1]-posOfCurCell;
1309 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1310 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1311 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1315 switch(cm.getDimension())
1319 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1320 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1321 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1326 int nbOfFaces,lgthOfPolyhConn;
1327 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1328 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1333 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1337 ret=ret || (newType!=type);
1338 conn[newPos]=newType;
1340 posOfCurCell=index[i+1];
1345 std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1346 newPos+=lgthOfCurCell;
1347 posOfCurCell+=lgthOfCurCell;
1351 if(newPos!=initMeshLgth)
1352 _nodal_connec->reAlloc(newPos);
1359 * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1360 * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1361 * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells.
1363 * \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
1366 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1368 checkFullyDefined();
1369 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1370 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1371 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1372 coords->recenterForMaxPrecision(eps);
1374 int nbOfCells=getNumberOfCells();
1375 const int *conn=_nodal_connec->getConstPointer();
1376 const int *index=_nodal_connec_index->getConstPointer();
1377 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1378 connINew->alloc(nbOfCells+1,1);
1379 int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1380 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1382 for(int i=0;i<nbOfCells;i++,connINewPtr++)
1384 if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1386 SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1390 connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1391 *connINewPtr=connNew->getNumberOfTuples();
1394 setConnectivity(connNew,connINew,false);
1398 * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1399 * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1400 * the format of returned DataArrayInt instance.
1402 * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1403 * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1405 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1407 checkConnectivityFullyDefined();
1408 int nbOfCells=getNumberOfCells();
1409 const int *connIndex=_nodal_connec_index->getConstPointer();
1410 const int *conn=_nodal_connec->getConstPointer();
1411 const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1412 int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1413 std::vector<bool> retS(maxElt,false);
1414 for(int i=0;i<nbOfCells;i++)
1415 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1419 for(int i=0;i<maxElt;i++)
1422 DataArrayInt *ret=DataArrayInt::New();
1424 int *retPtr=ret->getPointer();
1425 for(int i=0;i<maxElt;i++)
1432 * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1433 * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1435 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1437 int nbOfNodes((int)nodeIdsInUse.size()),nbOfCells(getNumberOfCells());
1438 const int *connIndex(_nodal_connec_index->getConstPointer()),*conn(_nodal_connec->getConstPointer());
1439 for(int i=0;i<nbOfCells;i++)
1440 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1443 if(conn[j]<nbOfNodes)
1444 nodeIdsInUse[conn[j]]=true;
1447 std::ostringstream oss; oss << "MEDCouplingUMesh::computeNodeIdsAlg : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1448 throw INTERP_KERNEL::Exception(oss.str().c_str());
1454 * Finds nodes not used in any cell and returns an array giving a new id to every node
1455 * by excluding the unused nodes, for which the array holds -1. The result array is
1456 * a mapping in "Old to New" mode.
1457 * \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1458 * \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1459 * this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1460 * if the node is unused or a new id else. The caller is to delete this
1461 * array using decrRef() as it is no more needed.
1462 * \throw If the coordinates array is not set.
1463 * \throw If the nodal connectivity of cells is not defined.
1464 * \throw If the nodal connectivity includes an invalid id.
1466 * \if ENABLE_EXAMPLES
1467 * \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1468 * \ref py_mcumesh_getNodeIdsInUse "Here is a Python example".
1470 * \sa computeFetchedNodeIds, computeNodeIdsAlg()
1472 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1475 int nbOfNodes(getNumberOfNodes());
1476 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1477 ret->alloc(nbOfNodes,1);
1478 int *traducer=ret->getPointer();
1479 std::fill(traducer,traducer+nbOfNodes,-1);
1480 int nbOfCells=getNumberOfCells();
1481 const int *connIndex=_nodal_connec_index->getConstPointer();
1482 const int *conn=_nodal_connec->getConstPointer();
1483 for(int i=0;i<nbOfCells;i++)
1484 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1487 if(conn[j]<nbOfNodes)
1488 traducer[conn[j]]=1;
1491 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1492 throw INTERP_KERNEL::Exception(oss.str().c_str());
1495 nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1496 std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1501 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1502 * For each cell in \b this the number of nodes constituting cell is computed.
1503 * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1504 * So for pohyhedrons some nodes can be counted several times in the returned result.
1506 * \return a newly allocated array
1507 * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1509 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1511 checkConnectivityFullyDefined();
1512 int nbOfCells=getNumberOfCells();
1513 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1514 ret->alloc(nbOfCells,1);
1515 int *retPtr=ret->getPointer();
1516 const int *conn=getNodalConnectivity()->getConstPointer();
1517 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1518 for(int i=0;i<nbOfCells;i++,retPtr++)
1520 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1521 *retPtr=connI[i+1]-connI[i]-1;
1523 *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1529 * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1530 * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1532 * \return DataArrayInt * - new object to be deallocated by the caller.
1533 * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1535 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1537 checkConnectivityFullyDefined();
1538 int nbOfCells=getNumberOfCells();
1539 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1540 ret->alloc(nbOfCells,1);
1541 int *retPtr=ret->getPointer();
1542 const int *conn=getNodalConnectivity()->getConstPointer();
1543 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1544 for(int i=0;i<nbOfCells;i++,retPtr++)
1546 std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1547 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1548 *retPtr=(int)s.size();
1552 *retPtr=(int)s.size();
1559 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1560 * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1562 * \return a newly allocated array
1564 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1566 checkConnectivityFullyDefined();
1567 int nbOfCells=getNumberOfCells();
1568 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1569 ret->alloc(nbOfCells,1);
1570 int *retPtr=ret->getPointer();
1571 const int *conn=getNodalConnectivity()->getConstPointer();
1572 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1573 for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1575 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1576 *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1582 * Removes unused nodes (the node coordinates array is shorten) and returns an array
1583 * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1584 * array mean that the corresponding old node is no more used.
1585 * \return DataArrayInt * - a new instance of DataArrayInt of length \a
1586 * this->getNumberOfNodes() before call of this method. The caller is to
1587 * delete this array using decrRef() as it is no more needed.
1588 * \throw If the coordinates array is not set.
1589 * \throw If the nodal connectivity of cells is not defined.
1590 * \throw If the nodal connectivity includes an invalid id.
1591 * \sa areAllNodesFetched
1593 * \if ENABLE_EXAMPLES
1594 * \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1595 * \ref py_mcumesh_zipCoordsTraducer "Here is a Python example".
1598 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1600 return MEDCouplingPointSet::zipCoordsTraducer();
1604 * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1605 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1607 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1612 return AreCellsEqual0(conn,connI,cell1,cell2);
1614 return AreCellsEqual1(conn,connI,cell1,cell2);
1616 return AreCellsEqual2(conn,connI,cell1,cell2);
1618 return AreCellsEqual3(conn,connI,cell1,cell2);
1620 return AreCellsEqual7(conn,connI,cell1,cell2);
1622 throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1626 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1628 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1630 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1631 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1636 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1638 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1640 int sz=connI[cell1+1]-connI[cell1];
1641 if(sz==connI[cell2+1]-connI[cell2])
1643 if(conn[connI[cell1]]==conn[connI[cell2]])
1645 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1646 unsigned dim=cm.getDimension();
1652 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1653 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1654 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1655 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1656 return work!=tmp+sz1?1:0;
1659 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1662 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1669 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1671 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1673 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1675 if(conn[connI[cell1]]==conn[connI[cell2]])
1677 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1678 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1686 * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1688 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1690 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1692 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1693 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1700 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1702 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1704 int sz=connI[cell1+1]-connI[cell1];
1705 if(sz==connI[cell2+1]-connI[cell2])
1707 if(conn[connI[cell1]]==conn[connI[cell2]])
1709 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1710 unsigned dim=cm.getDimension();
1716 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1717 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1718 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1719 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1724 std::reverse_iterator<int *> it1((int *)tmp+sz1);
1725 std::reverse_iterator<int *> it2((int *)tmp);
1726 if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1732 return work!=tmp+sz1?1:0;
1735 {//case of SEG2 and SEG3
1736 if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1738 if(!cm.isQuadratic())
1740 std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1741 std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1742 if(std::equal(it1,it2,conn+connI[cell2]+1))
1748 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])
1755 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1762 * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1763 * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1764 * and result remains unchanged.
1765 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1766 * If in 'candidates' pool -1 value is considered as an empty value.
1767 * WARNING this method returns only ONE set of result !
1769 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1771 if(candidates.size()<1)
1774 std::vector<int>::const_iterator iter=candidates.begin();
1775 int start=(*iter++);
1776 for(;iter!=candidates.end();iter++)
1778 int status=AreCellsEqual(conn,connI,start,*iter,compType);
1783 result->pushBackSilent(start);
1787 result->pushBackSilent(*iter);
1789 result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1796 * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1797 * This method keeps the coordiantes of \a this. This method is time consuming and is called
1799 * \param [in] compType input specifying the technique used to compare cells each other.
1800 * - 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.
1801 * - 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)
1802 * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1803 * - 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
1804 * can be used for users not sensitive to orientation of cell
1805 * \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.
1806 * \param [out] commonCells
1807 * \param [out] commonCellsI
1808 * \return the correspondance array old to new in a newly allocated array.
1811 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1813 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1814 getReverseNodalConnectivity(revNodal,revNodalI);
1815 FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1818 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1819 DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr)
1821 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1822 int nbOfCells=nodalI->getNumberOfTuples()-1;
1823 commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1824 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1825 const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1826 std::vector<bool> isFetched(nbOfCells,false);
1829 for(int i=0;i<nbOfCells;i++)
1833 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1834 std::vector<int> v,v2;
1835 if(connOfNode!=connPtr+connIPtr[i+1])
1837 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1838 v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1841 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1845 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1846 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1847 v2.resize(std::distance(v2.begin(),it));
1851 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1853 int pos=commonCellsI->back();
1854 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1855 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1856 isFetched[*it]=true;
1864 for(int i=startCellId;i<nbOfCells;i++)
1868 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1869 std::vector<int> v,v2;
1870 if(connOfNode!=connPtr+connIPtr[i+1])
1872 v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1875 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1879 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1880 v2.resize(std::distance(v2.begin(),it));
1884 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1886 int pos=commonCellsI->back();
1887 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1888 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1889 isFetched[*it]=true;
1895 commonCellsArr=commonCells.retn();
1896 commonCellsIArr=commonCellsI.retn();
1900 * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1901 * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1902 * than \a other->getNumberOfCells() in the returned array means that there is no
1903 * corresponding cell in \a this mesh.
1904 * It is expected that \a this and \a other meshes share the same node coordinates
1905 * array, if it is not so an exception is thrown.
1906 * \param [in] other - the mesh to compare with.
1907 * \param [in] compType - specifies a cell comparison technique. For meaning of its
1908 * valid values [0,1,2], see zipConnectivityTraducer().
1909 * \param [out] arr - a new instance of DataArrayInt returning correspondence
1910 * between cells of the two meshes. It contains \a other->getNumberOfCells()
1911 * values. The caller is to delete this array using
1912 * decrRef() as it is no more needed.
1913 * \return bool - \c true if all cells of \a other mesh are present in the \a this
1916 * \if ENABLE_EXAMPLES
1917 * \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1918 * \ref py_mcumesh_areCellsIncludedIn "Here is a Python example".
1920 * \sa checkDeepEquivalOnSameNodesWith()
1921 * \sa checkGeoEquivalWith()
1923 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1925 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1926 int nbOfCells=getNumberOfCells();
1927 static const int possibleCompType[]={0,1,2};
1928 if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1930 std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1931 std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1933 throw INTERP_KERNEL::Exception(oss.str().c_str());
1935 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1936 arr=o2n->substr(nbOfCells);
1937 arr->setName(other->getName());
1939 if(other->getNumberOfCells()==0)
1941 return arr->getMaxValue(tmp)<nbOfCells;
1945 * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1946 * This method tries to determine if \b other is fully included in \b this.
1947 * The main difference is that this method is not expected to throw exception.
1948 * This method has two outputs :
1950 * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1951 * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1953 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1955 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1956 DataArrayInt *commonCells=0,*commonCellsI=0;
1957 int thisNbCells=getNumberOfCells();
1958 mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1959 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1960 const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1961 int otherNbCells=other->getNumberOfCells();
1962 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1963 arr2->alloc(otherNbCells,1);
1964 arr2->fillWithZero();
1965 int *arr2Ptr=arr2->getPointer();
1966 int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1967 for(int i=0;i<nbOfCommon;i++)
1969 int start=commonCellsPtr[commonCellsIPtr[i]];
1970 if(start<thisNbCells)
1972 for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1974 int sig=commonCellsPtr[j]>0?1:-1;
1975 int val=std::abs(commonCellsPtr[j])-1;
1976 if(val>=thisNbCells)
1977 arr2Ptr[val-thisNbCells]=sig*(start+1);
1981 arr2->setName(other->getName());
1982 if(arr2->presenceOfValue(0))
1988 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1991 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1992 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1994 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1995 std::vector<const MEDCouplingUMesh *> ms(2);
1998 return MergeUMeshesOnSameCoords(ms);
2002 * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
2003 * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
2004 * cellIds is not given explicitely but by a range python like.
2006 * \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.
2007 * \return a newly allocated
2009 * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
2010 * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
2012 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const
2014 if(getMeshDimension()!=-1)
2015 return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
2018 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
2020 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2022 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2024 return const_cast<MEDCouplingUMesh *>(this);
2029 * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
2030 * The result mesh shares or not the node coordinates array with \a this mesh depending
2031 * on \a keepCoords parameter.
2032 * \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
2033 * to write this mesh to the MED file, its cells must be sorted using
2034 * sortCellsInMEDFileFrmt().
2035 * \param [in] begin - an array of cell ids to include to the new mesh.
2036 * \param [in] end - a pointer to last-plus-one-th element of \a begin.
2037 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2038 * array of \a this mesh, else "free" nodes are removed from the result mesh
2039 * by calling zipCoords().
2040 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2041 * to delete this mesh using decrRef() as it is no more needed.
2042 * \throw If the coordinates array is not set.
2043 * \throw If the nodal connectivity of cells is not defined.
2044 * \throw If any cell id in the array \a begin is not valid.
2046 * \if ENABLE_EXAMPLES
2047 * \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
2048 * \ref py_mcumesh_buildPartOfMySelf "Here is a Python example".
2051 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2053 if(getMeshDimension()!=-1)
2054 return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
2058 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2060 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2062 return const_cast<MEDCouplingUMesh *>(this);
2067 * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2069 * 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.
2070 * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2071 * The number of cells of \b this will remain the same with this method.
2073 * \param [in] begin begin of cell ids (included) of cells in this to assign
2074 * \param [in] end end of cell ids (excluded) of cells in this to assign
2075 * \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 ).
2076 * Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2078 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2080 checkConnectivityFullyDefined();
2081 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2082 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2083 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2084 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2086 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2087 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2088 throw INTERP_KERNEL::Exception(oss.str().c_str());
2090 int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2091 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2093 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2094 throw INTERP_KERNEL::Exception(oss.str().c_str());
2096 int nbOfCells=getNumberOfCells();
2097 bool easyAssign=true;
2098 const int *connI=_nodal_connec_index->getConstPointer();
2099 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2100 for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2102 if(*it>=0 && *it<nbOfCells)
2104 easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2108 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2109 throw INTERP_KERNEL::Exception(oss.str().c_str());
2114 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2119 DataArrayInt *arrOut=0,*arrIOut=0;
2120 MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2122 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2123 setConnectivity(arrOut,arrIOut,true);
2127 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2129 checkConnectivityFullyDefined();
2130 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2131 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2132 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2133 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2135 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2136 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2137 throw INTERP_KERNEL::Exception(oss.str().c_str());
2139 int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2140 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2142 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2143 throw INTERP_KERNEL::Exception(oss.str().c_str());
2145 int nbOfCells=getNumberOfCells();
2146 bool easyAssign=true;
2147 const int *connI=_nodal_connec_index->getConstPointer();
2148 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2150 for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2152 if(it>=0 && it<nbOfCells)
2154 easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2158 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2159 throw INTERP_KERNEL::Exception(oss.str().c_str());
2164 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2169 DataArrayInt *arrOut=0,*arrIOut=0;
2170 MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2172 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2173 setConnectivity(arrOut,arrIOut,true);
2178 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2179 * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2180 * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2181 * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2183 * \param [in] begin input start of array of node ids.
2184 * \param [in] end input end of array of node ids.
2185 * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2186 * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2188 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2190 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2191 checkConnectivityFullyDefined();
2193 int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2194 std::vector<bool> fastFinder(sz,false);
2195 for(const int *work=begin;work!=end;work++)
2196 if(*work>=0 && *work<sz)
2197 fastFinder[*work]=true;
2198 int nbOfCells=getNumberOfCells();
2199 const int *conn=getNodalConnectivity()->getConstPointer();
2200 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2201 for(int i=0;i<nbOfCells;i++)
2203 int ref=0,nbOfHit=0;
2204 for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2208 if(fastFinder[*work2])
2211 if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2212 cellIdsKept->pushBackSilent(i);
2214 cellIdsKeptArr=cellIdsKept.retn();
2218 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2219 * this->getMeshDimension(), that bound some cells of \a this mesh.
2220 * The cells of lower dimension to include to the result mesh are selected basing on
2221 * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2222 * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2223 * ==\c false, a cell is copied if any its node is in the array of node ids. The
2224 * created mesh shares the node coordinates array with \a this mesh.
2225 * \param [in] begin - the array of node ids.
2226 * \param [in] end - a pointer to the (last+1)-th element of \a begin.
2227 * \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2228 * array \a begin are added, else cells whose any node is in the
2229 * array \a begin are added.
2230 * \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2231 * to delete this mesh using decrRef() as it is no more needed.
2232 * \throw If the coordinates array is not set.
2233 * \throw If the nodal connectivity of cells is not defined.
2234 * \throw If any node id in \a begin is not valid.
2236 * \if ENABLE_EXAMPLES
2237 * \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2238 * \ref py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2241 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2243 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2244 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2245 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2246 desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2247 return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2251 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2252 * this->getMeshDimension(), which bound only one cell of \a this mesh.
2253 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2254 * array of \a this mesh, else "free" nodes are removed from the result mesh
2255 * by calling zipCoords().
2256 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2257 * to delete this mesh using decrRef() as it is no more needed.
2258 * \throw If the coordinates array is not set.
2259 * \throw If the nodal connectivity of cells is not defined.
2261 * \if ENABLE_EXAMPLES
2262 * \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2263 * \ref py_mcumesh_buildBoundaryMesh "Here is a Python example".
2266 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2268 DataArrayInt *desc=DataArrayInt::New();
2269 DataArrayInt *descIndx=DataArrayInt::New();
2270 DataArrayInt *revDesc=DataArrayInt::New();
2271 DataArrayInt *revDescIndx=DataArrayInt::New();
2273 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2276 descIndx->decrRef();
2277 int nbOfCells=meshDM1->getNumberOfCells();
2278 const int *revDescIndxC=revDescIndx->getConstPointer();
2279 std::vector<int> boundaryCells;
2280 for(int i=0;i<nbOfCells;i++)
2281 if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2282 boundaryCells.push_back(i);
2283 revDescIndx->decrRef();
2284 MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2289 * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2290 * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2291 * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown.
2293 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2295 checkFullyDefined();
2296 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2297 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2298 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2299 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2301 buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2302 desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2304 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2305 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2306 const int *revDescPtr=revDesc->getConstPointer();
2307 const int *revDescIndxPtr=revDescIndx->getConstPointer();
2308 int nbOfCells=getNumberOfCells();
2309 std::vector<bool> ret1(nbOfCells,false);
2311 for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2312 if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2313 { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2315 DataArrayInt *ret2=DataArrayInt::New();
2317 int *ret2Ptr=ret2->getPointer();
2319 for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2322 ret2->setName("BoundaryCells");
2327 * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2328 * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2329 * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2330 * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2332 * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2333 * This method method returns cells ids set s = s1 + s2 where :
2335 * - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2336 * - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2338 * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2339 * are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2341 * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2342 * \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
2343 * cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2345 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2347 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2348 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2349 checkConnectivityFullyDefined();
2350 otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2351 if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2352 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2353 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2354 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2355 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2356 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2357 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2358 const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2359 DataArrayInt *idsOtherInConsti=0;
2360 bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2361 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2363 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2365 for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2366 s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2367 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2368 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2369 DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2370 ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2371 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2372 ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2373 neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2374 RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2375 neighThisPartAuto=0;
2376 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2377 const int li[2]={0,1};
2378 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2379 s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2380 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2383 cellIdsRk0=s0arr.retn();
2384 cellIdsRk1=s_renum1.retn();
2388 * 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
2389 * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2391 * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2393 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2395 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2396 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2397 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2398 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2400 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2401 revDesc=0; desc=0; descIndx=0;
2402 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2403 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2404 return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2408 * Finds nodes lying on the boundary of \a this mesh.
2409 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2410 * nodes. The caller is to delete this array using decrRef() as it is no
2412 * \throw If the coordinates array is not set.
2413 * \throw If the nodal connectivity of cells is node defined.
2415 * \if ENABLE_EXAMPLES
2416 * \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2417 * \ref py_mcumesh_findBoundaryNodes "Here is a Python example".
2420 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2422 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2423 return skin->computeFetchedNodeIds();
2426 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2429 return const_cast<MEDCouplingUMesh *>(this);
2433 * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2434 * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2435 * 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.
2436 * 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.
2437 * 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.
2439 * \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
2440 * parameter is altered during the call.
2441 * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2442 * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2443 * \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.
2445 * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2447 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2448 DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const
2450 checkFullyDefined();
2451 otherDimM1OnSameCoords.checkFullyDefined();
2452 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2453 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2454 if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2455 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2456 DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2457 findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2458 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2459 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2460 s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2461 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2462 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2463 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2464 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2465 cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2467 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2468 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2469 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2470 DataArrayInt *idsTmp=0;
2471 bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2472 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2474 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2475 MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2476 DataArrayInt *tmp0=0,*tmp1=0;
2477 ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2478 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2479 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2480 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2481 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2482 cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2483 cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2485 cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2486 cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2487 nodeIdsToDuplicate=s3.retn();
2491 * This method operates a modification of the connectivity and coords in \b this.
2492 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2493 * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2494 * 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
2495 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2496 * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2498 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2500 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2501 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2503 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2505 int nbOfNodes=getNumberOfNodes();
2506 duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2507 duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2511 * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of
2512 * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range !
2514 * \param [in] offset - specifies the offset to be applied on each element of connectivity.
2516 * \sa renumberNodesInConn
2518 void MEDCouplingUMesh::renumberNodesWithOffsetInConn(int offset)
2520 checkConnectivityFullyDefined();
2521 int *conn(getNodalConnectivity()->getPointer());
2522 const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2523 int nbOfCells(getNumberOfCells());
2524 for(int i=0;i<nbOfCells;i++)
2525 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2527 int& node=conn[iconn];
2528 if(node>=0)//avoid polyhedron separator
2533 _nodal_connec->declareAsNew();
2538 * Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
2539 * 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
2542 void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& newNodeNumbersO2N)
2544 checkConnectivityFullyDefined();
2545 int *conn(getNodalConnectivity()->getPointer());
2546 const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2547 int nbOfCells(getNumberOfCells());
2548 for(int i=0;i<nbOfCells;i++)
2549 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2551 int& node=conn[iconn];
2552 if(node>=0)//avoid polyhedron separator
2554 INTERP_KERNEL::HashMap<int,int>::const_iterator it(newNodeNumbersO2N.find(node));
2555 if(it!=newNodeNumbersO2N.end())
2561 std::ostringstream oss; oss << "MEDCouplingUMesh::renumberNodesInConn(map) : presence in connectivity for cell #" << i << " of node #" << node << " : Not in map !";
2562 throw INTERP_KERNEL::Exception(oss.str().c_str());
2566 _nodal_connec->declareAsNew();
2571 * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2572 * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2573 * This method is a generalization of shiftNodeNumbersInConn().
2574 * \warning This method performs no check of validity of new ids. **Use it with care !**
2575 * \param [in] newNodeNumbersO2N - a permutation array, of length \a
2576 * this->getNumberOfNodes(), in "Old to New" mode.
2577 * See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2578 * \throw If the nodal connectivity of cells is not defined.
2580 * \if ENABLE_EXAMPLES
2581 * \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2582 * \ref py_mcumesh_renumberNodesInConn "Here is a Python example".
2585 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2587 checkConnectivityFullyDefined();
2588 int *conn=getNodalConnectivity()->getPointer();
2589 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2590 int nbOfCells(getNumberOfCells());
2591 for(int i=0;i<nbOfCells;i++)
2592 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2594 int& node=conn[iconn];
2595 if(node>=0)//avoid polyhedron separator
2597 node=newNodeNumbersO2N[node];
2600 _nodal_connec->declareAsNew();
2605 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2606 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2607 * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2609 * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2611 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2613 checkConnectivityFullyDefined();
2614 int *conn=getNodalConnectivity()->getPointer();
2615 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2616 int nbOfCells=getNumberOfCells();
2617 for(int i=0;i<nbOfCells;i++)
2618 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2620 int& node=conn[iconn];
2621 if(node>=0)//avoid polyhedron separator
2626 _nodal_connec->declareAsNew();
2631 * This method operates a modification of the connectivity in \b this.
2632 * 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.
2633 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2634 * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2635 * 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
2636 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2637 * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2639 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2640 * As an another consequense after the call of this method \b this can be transiently non cohrent.
2642 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2643 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2644 * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ).
2646 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2648 checkConnectivityFullyDefined();
2649 std::map<int,int> m;
2651 for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2653 int *conn=getNodalConnectivity()->getPointer();
2654 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2655 int nbOfCells=getNumberOfCells();
2656 for(int i=0;i<nbOfCells;i++)
2657 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2659 int& node=conn[iconn];
2660 if(node>=0)//avoid polyhedron separator
2662 std::map<int,int>::iterator it=m.find(node);
2671 * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2673 * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2674 * After the call of this method the number of cells remains the same as before.
2676 * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2677 * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2678 * be strictly in [0;this->getNumberOfCells()).
2680 * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2681 * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2682 * should be contained in[0;this->getNumberOfCells()).
2684 * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2686 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2688 checkConnectivityFullyDefined();
2689 int nbCells=getNumberOfCells();
2690 const int *array=old2NewBg;
2692 array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2694 const int *conn=_nodal_connec->getConstPointer();
2695 const int *connI=_nodal_connec_index->getConstPointer();
2696 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2697 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2698 const int *n2oPtr=n2o->begin();
2699 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2700 newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2701 newConn->copyStringInfoFrom(*_nodal_connec);
2702 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2703 newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2704 newConnI->copyStringInfoFrom(*_nodal_connec_index);
2706 int *newC=newConn->getPointer();
2707 int *newCI=newConnI->getPointer();
2710 for(int i=0;i<nbCells;i++)
2713 int nbOfElts=connI[pos+1]-connI[pos];
2714 newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2719 setConnectivity(newConn,newConnI);
2721 free(const_cast<int *>(array));
2725 * Finds cells whose bounding boxes intersect a given bounding box.
2726 * \param [in] bbox - an array defining the bounding box via coordinates of its
2727 * extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2729 * \param [in] eps - a factor used to increase size of the bounding box of cell
2730 * before comparing it with \a bbox. This factor is multiplied by the maximal
2731 * extent of the bounding box of cell to produce an addition to this bounding box.
2732 * \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2733 * cells. The caller is to delete this array using decrRef() as it is no more
2735 * \throw If the coordinates array is not set.
2736 * \throw If the nodal connectivity of cells is not defined.
2738 * \if ENABLE_EXAMPLES
2739 * \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2740 * \ref py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2743 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2745 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2746 if(getMeshDimension()==-1)
2748 elems->pushBackSilent(0);
2749 return elems.retn();
2751 int dim=getSpaceDimension();
2752 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2753 const int* conn = getNodalConnectivity()->getConstPointer();
2754 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2755 const double* coords = getCoords()->getConstPointer();
2756 int nbOfCells=getNumberOfCells();
2757 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2759 for (int i=0; i<dim; i++)
2761 elem_bb[i*2]=std::numeric_limits<double>::max();
2762 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2765 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2767 int node= conn[inode];
2768 if(node>=0)//avoid polyhedron separator
2770 for (int idim=0; idim<dim; idim++)
2772 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2774 elem_bb[idim*2] = coords[node*dim+idim] ;
2776 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2778 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2783 if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2784 elems->pushBackSilent(ielem);
2786 return elems.retn();
2790 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2791 * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2792 * added in 'elems' parameter.
2794 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2796 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2797 if(getMeshDimension()==-1)
2799 elems->pushBackSilent(0);
2800 return elems.retn();
2802 int dim=getSpaceDimension();
2803 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2804 const int* conn = getNodalConnectivity()->getConstPointer();
2805 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2806 const double* coords = getCoords()->getConstPointer();
2807 int nbOfCells=getNumberOfCells();
2808 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2810 for (int i=0; i<dim; i++)
2812 elem_bb[i*2]=std::numeric_limits<double>::max();
2813 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2816 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2818 int node= conn[inode];
2819 if(node>=0)//avoid polyhedron separator
2821 for (int idim=0; idim<dim; idim++)
2823 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2825 elem_bb[idim*2] = coords[node*dim+idim] ;
2827 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2829 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2834 if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2835 elems->pushBackSilent(ielem);
2837 return elems.retn();
2841 * Returns a type of a cell by its id.
2842 * \param [in] cellId - the id of the cell of interest.
2843 * \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2844 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2846 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2848 const int *ptI=_nodal_connec_index->getConstPointer();
2849 const int *pt=_nodal_connec->getConstPointer();
2850 if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2851 return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2854 std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2855 throw INTERP_KERNEL::Exception(oss.str().c_str());
2860 * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2861 * This method does not throw exception if geometric type \a type is not in \a this.
2862 * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2863 * The coordinates array is not considered here.
2865 * \param [in] type the geometric type
2866 * \return cell ids in this having geometric type \a type.
2868 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2871 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2873 checkConnectivityFullyDefined();
2874 int nbCells=getNumberOfCells();
2875 int mdim=getMeshDimension();
2876 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2877 if(mdim!=(int)cm.getDimension())
2878 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2879 const int *ptI=_nodal_connec_index->getConstPointer();
2880 const int *pt=_nodal_connec->getConstPointer();
2881 for(int i=0;i<nbCells;i++)
2883 if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2884 ret->pushBackSilent(i);
2890 * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2892 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2894 const int *ptI=_nodal_connec_index->getConstPointer();
2895 const int *pt=_nodal_connec->getConstPointer();
2896 int nbOfCells=getNumberOfCells();
2898 for(int i=0;i<nbOfCells;i++)
2899 if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2905 * Returns the nodal connectivity of a given cell.
2906 * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2907 * all returned node ids can be used in getCoordinatesOfNode().
2908 * \param [in] cellId - an id of the cell of interest.
2909 * \param [in,out] conn - a vector where the node ids are appended. It is not
2910 * cleared before the appending.
2911 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2913 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2915 const int *ptI=_nodal_connec_index->getConstPointer();
2916 const int *pt=_nodal_connec->getConstPointer();
2917 for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2922 std::string MEDCouplingUMesh::simpleRepr() const
2924 static const char msg0[]="No coordinates specified !";
2925 std::ostringstream ret;
2926 ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2927 ret << "Description of mesh : \"" << getDescription() << "\"\n";
2929 double tt=getTime(tmpp1,tmpp2);
2930 ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2931 ret << "Iteration : " << tmpp1 << " Order : " << tmpp2 << "\n";
2933 { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2935 { ret << " Mesh dimension has not been set or is invalid !"; }
2938 const int spaceDim=getSpaceDimension();
2939 ret << spaceDim << "\nInfo attached on space dimension : ";
2940 for(int i=0;i<spaceDim;i++)
2941 ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2945 ret << msg0 << "\n";
2946 ret << "Number of nodes : ";
2948 ret << getNumberOfNodes() << "\n";
2950 ret << msg0 << "\n";
2951 ret << "Number of cells : ";
2952 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2953 ret << getNumberOfCells() << "\n";
2955 ret << "No connectivity specified !" << "\n";
2956 ret << "Cell types present : ";
2957 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2959 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2960 ret << cm.getRepr() << " ";
2966 std::string MEDCouplingUMesh::advancedRepr() const
2968 std::ostringstream ret;
2969 ret << simpleRepr();
2970 ret << "\nCoordinates array : \n___________________\n\n";
2972 _coords->reprWithoutNameStream(ret);
2974 ret << "No array set !\n";
2975 ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2976 reprConnectivityOfThisLL(ret);
2981 * This method returns a C++ code that is a dump of \a this.
2982 * This method will throw if this is not fully defined.
2984 std::string MEDCouplingUMesh::cppRepr() const
2986 static const char coordsName[]="coords";
2987 static const char connName[]="conn";
2988 static const char connIName[]="connI";
2989 checkFullyDefined();
2990 std::ostringstream ret; ret << "// coordinates" << std::endl;
2991 _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2992 _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2993 _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2994 ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2995 ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2996 ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2997 ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
3001 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
3003 std::ostringstream ret;
3004 reprConnectivityOfThisLL(ret);
3009 * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
3010 * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
3011 * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
3014 * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
3015 * 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
3016 * with number of tuples set to 0, if not the array is taken as this in the returned instance.
3018 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
3020 int mdim=getMeshDimension();
3022 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
3023 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
3024 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
3025 bool needToCpyCT=true;
3028 tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
3036 if(!_nodal_connec_index)
3038 tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
3043 tmp2=_nodal_connec_index;
3046 ret->setConnectivity(tmp1,tmp2,false);
3051 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
3052 ret->setCoords(coords);
3055 ret->setCoords(_coords);
3059 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
3061 if(_nodal_connec!=0 && _nodal_connec_index!=0)
3063 int nbOfCells=getNumberOfCells();
3064 const int *c=_nodal_connec->getConstPointer();
3065 const int *ci=_nodal_connec_index->getConstPointer();
3066 for(int i=0;i<nbOfCells;i++)
3068 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3069 stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3070 std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3075 stream << "Connectivity not defined !\n";
3078 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3080 const int *ptI=_nodal_connec_index->getConstPointer();
3081 const int *pt=_nodal_connec->getConstPointer();
3082 if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3083 return ptI[cellId+1]-ptI[cellId]-1;
3085 return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3089 * Returns types of cells of the specified part of \a this mesh.
3090 * This method avoids computing sub-mesh explicitely to get its types.
3091 * \param [in] begin - an array of cell ids of interest.
3092 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3093 * \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3094 * describing the cell types.
3095 * \throw If the coordinates array is not set.
3096 * \throw If the nodal connectivity of cells is not defined.
3097 * \sa getAllGeoTypes()
3099 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3101 checkFullyDefined();
3102 std::set<INTERP_KERNEL::NormalizedCellType> ret;
3103 const int *conn=_nodal_connec->getConstPointer();
3104 const int *connIndex=_nodal_connec_index->getConstPointer();
3105 for(const int *w=begin;w!=end;w++)
3106 ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3111 * Defines the nodal connectivity using given connectivity arrays. Optionally updates
3112 * a set of types of cells constituting \a this mesh.
3113 * This method is for advanced users having prepared their connectivity before. For
3114 * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3115 * \param [in] conn - the nodal connectivity array.
3116 * \param [in] connIndex - the nodal connectivity index array.
3117 * \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3120 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3122 DataArrayInt::SetArrayIn(conn,_nodal_connec);
3123 DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3124 if(isComputingTypes)
3130 * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
3131 * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3133 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3134 _nodal_connec(0),_nodal_connec_index(0),
3135 _types(other._types)
3137 if(other._nodal_connec)
3138 _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3139 if(other._nodal_connec_index)
3140 _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3143 MEDCouplingUMesh::~MEDCouplingUMesh()
3146 _nodal_connec->decrRef();
3147 if(_nodal_connec_index)
3148 _nodal_connec_index->decrRef();
3152 * Recomputes a set of cell types of \a this mesh. For more info see
3153 * \ref MEDCouplingUMeshNodalConnectivity.
3155 void MEDCouplingUMesh::computeTypes()
3157 ComputeAllTypesInternal(_types,_nodal_connec,_nodal_connec_index);
3161 * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3163 void MEDCouplingUMesh::checkFullyDefined() const
3165 if(!_nodal_connec_index || !_nodal_connec || !_coords)
3166 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3170 * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3172 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3174 if(!_nodal_connec_index || !_nodal_connec)
3175 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3179 * Returns a number of cells constituting \a this mesh.
3180 * \return int - the number of cells in \a this mesh.
3181 * \throw If the nodal connectivity of cells is not defined.
3183 int MEDCouplingUMesh::getNumberOfCells() const
3185 if(_nodal_connec_index)
3186 return _nodal_connec_index->getNumberOfTuples()-1;
3191 throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3195 * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3196 * mesh. For more info see \ref MEDCouplingMeshesPage.
3197 * \return int - the dimension of \a this mesh.
3198 * \throw If the mesh dimension is not defined using setMeshDimension().
3200 int MEDCouplingUMesh::getMeshDimension() const
3203 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3208 * Returns a length of the nodal connectivity array.
3209 * This method is for test reason. Normally the integer returned is not useable by
3210 * user. For more info see \ref MEDCouplingUMeshNodalConnectivity.
3211 * \return int - the length of the nodal connectivity array.
3213 int MEDCouplingUMesh::getMeshLength() const
3215 return _nodal_connec->getNbOfElems();
3219 * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3221 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3223 MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3224 tinyInfo.push_back(getMeshDimension());
3225 tinyInfo.push_back(getNumberOfCells());
3227 tinyInfo.push_back(getMeshLength());
3229 tinyInfo.push_back(-1);
3233 * First step of unserialization process.
3235 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3237 return tinyInfo[6]<=0;
3241 * Second step of serialization process.
3242 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3244 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3246 MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3248 a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3252 * Third and final step of serialization process.
3254 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3256 MEDCouplingPointSet::serialize(a1,a2);
3257 if(getMeshDimension()>-1)
3259 a1=DataArrayInt::New();
3260 a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3261 int *ptA1=a1->getPointer();
3262 const int *conn=getNodalConnectivity()->getConstPointer();
3263 const int *index=getNodalConnectivityIndex()->getConstPointer();
3264 ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3265 std::copy(conn,conn+getMeshLength(),ptA1);
3272 * Second and final unserialization process.
3273 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3275 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3277 MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3278 setMeshDimension(tinyInfo[5]);
3282 const int *recvBuffer=a1->getConstPointer();
3283 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3284 myConnecIndex->alloc(tinyInfo[6]+1,1);
3285 std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3286 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3287 myConnec->alloc(tinyInfo[7],1);
3288 std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3289 setConnectivity(myConnec, myConnecIndex);
3294 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3295 * CellIds are given using range specified by a start an end and step.
3297 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3299 checkFullyDefined();
3300 int ncell=getNumberOfCells();
3301 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3302 ret->_mesh_dim=_mesh_dim;
3303 ret->setCoords(_coords);
3304 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3305 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3306 int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3308 const int *conn=_nodal_connec->getConstPointer();
3309 const int *connIndex=_nodal_connec_index->getConstPointer();
3310 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3312 if(work>=0 && work<ncell)
3314 newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3318 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3319 throw INTERP_KERNEL::Exception(oss.str().c_str());
3322 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3323 int *newConnPtr=newConn->getPointer();
3324 std::set<INTERP_KERNEL::NormalizedCellType> types;
3326 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3328 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3329 newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3331 ret->setConnectivity(newConn,newConnI,false);
3333 ret->copyTinyInfoFrom(this);
3338 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3339 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3340 * The return newly allocated mesh will share the same coordinates as \a this.
3342 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3344 checkConnectivityFullyDefined();
3345 int ncell=getNumberOfCells();
3346 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3347 ret->_mesh_dim=_mesh_dim;
3348 ret->setCoords(_coords);
3349 std::size_t nbOfElemsRet=std::distance(begin,end);
3350 int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3352 const int *conn=_nodal_connec->getConstPointer();
3353 const int *connIndex=_nodal_connec_index->getConstPointer();
3355 for(const int *work=begin;work!=end;work++,newNbring++)
3357 if(*work>=0 && *work<ncell)
3358 connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3362 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3363 throw INTERP_KERNEL::Exception(oss.str().c_str());
3366 int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3367 int *connRetWork=connRet;
3368 std::set<INTERP_KERNEL::NormalizedCellType> types;
3369 for(const int *work=begin;work!=end;work++)
3371 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3372 connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3374 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3375 connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3376 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3377 connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3378 ret->setConnectivity(connRetArr,connIndexRetArr,false);
3380 ret->copyTinyInfoFrom(this);
3385 * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3387 * For 1D cells, the returned field contains lengths.<br>
3388 * For 2D cells, the returned field contains areas.<br>
3389 * For 3D cells, the returned field contains volumes.
3390 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3391 * orientation, i.e. the volume is always positive.
3392 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3393 * and one time . The caller is to delete this field using decrRef() as it is no
3396 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3398 std::string name="MeasureOfMesh_";
3400 int nbelem=getNumberOfCells();
3401 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3402 field->setName(name);
3403 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3404 array->alloc(nbelem,1);
3405 double *area_vol=array->getPointer();
3406 field->setArray(array) ; array=0;
3407 field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3408 field->synchronizeTimeWithMesh();
3409 if(getMeshDimension()!=-1)
3412 INTERP_KERNEL::NormalizedCellType type;
3413 int dim_space=getSpaceDimension();
3414 const double *coords=getCoords()->getConstPointer();
3415 const int *connec=getNodalConnectivity()->getConstPointer();
3416 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3417 for(int iel=0;iel<nbelem;iel++)
3419 ipt=connec_index[iel];
3420 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3421 area_vol[iel]=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[iel+1]-ipt-1,coords,dim_space);
3424 std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3428 area_vol[0]=std::numeric_limits<double>::max();
3430 return field.retn();
3434 * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3436 * For 1D cells, the returned array contains lengths.<br>
3437 * For 2D cells, the returned array contains areas.<br>
3438 * For 3D cells, the returned array contains volumes.
3439 * This method avoids building explicitly a part of \a this mesh to perform the work.
3440 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3441 * orientation, i.e. the volume is always positive.
3442 * \param [in] begin - an array of cell ids of interest.
3443 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3444 * \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3445 * delete this array using decrRef() as it is no more needed.
3447 * \if ENABLE_EXAMPLES
3448 * \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3449 * \ref py_mcumesh_getPartMeasureField "Here is a Python example".
3451 * \sa getMeasureField()
3453 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3455 std::string name="PartMeasureOfMesh_";
3457 int nbelem=(int)std::distance(begin,end);
3458 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3459 array->setName(name);
3460 array->alloc(nbelem,1);
3461 double *area_vol=array->getPointer();
3462 if(getMeshDimension()!=-1)
3465 INTERP_KERNEL::NormalizedCellType type;
3466 int dim_space=getSpaceDimension();
3467 const double *coords=getCoords()->getConstPointer();
3468 const int *connec=getNodalConnectivity()->getConstPointer();
3469 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3470 for(const int *iel=begin;iel!=end;iel++)
3472 ipt=connec_index[*iel];
3473 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3474 *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3477 std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3481 area_vol[0]=std::numeric_limits<double>::max();
3483 return array.retn();
3487 * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3488 * \a this one. The returned field contains the dual cell volume for each corresponding
3489 * node in \a this mesh. In other words, the field returns the getMeasureField() of
3490 * the dual mesh in P1 sens of \a this.<br>
3491 * For 1D cells, the returned field contains lengths.<br>
3492 * For 2D cells, the returned field contains areas.<br>
3493 * For 3D cells, the returned field contains volumes.
3494 * This method is useful to check "P1*" conservative interpolators.
3495 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3496 * orientation, i.e. the volume is always positive.
3497 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3498 * nodes and one time. The caller is to delete this array using decrRef() as
3499 * it is no more needed.
3501 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3503 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3504 std::string name="MeasureOnNodeOfMesh_";
3506 int nbNodes=getNumberOfNodes();
3507 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3508 double cst=1./((double)getMeshDimension()+1.);
3509 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3510 array->alloc(nbNodes,1);
3511 double *valsToFill=array->getPointer();
3512 std::fill(valsToFill,valsToFill+nbNodes,0.);
3513 const double *values=tmp->getArray()->getConstPointer();
3514 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3515 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3516 getReverseNodalConnectivity(da,daInd);
3517 const int *daPtr=da->getConstPointer();
3518 const int *daIPtr=daInd->getConstPointer();
3519 for(int i=0;i<nbNodes;i++)
3520 for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3521 valsToFill[i]+=cst*values[*cell];
3523 ret->setArray(array);
3528 * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3529 * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3530 * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3531 * and are normalized.
3532 * <br> \a this can be either
3533 * - a 2D mesh in 2D or 3D space or
3534 * - an 1D mesh in 2D space.
3536 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3537 * cells and one time. The caller is to delete this field using decrRef() as
3538 * it is no more needed.
3539 * \throw If the nodal connectivity of cells is not defined.
3540 * \throw If the coordinates array is not set.
3541 * \throw If the mesh dimension is not set.
3542 * \throw If the mesh and space dimension is not as specified above.
3544 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3546 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3547 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3548 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3549 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3550 int nbOfCells=getNumberOfCells();
3551 int nbComp=getMeshDimension()+1;
3552 array->alloc(nbOfCells,nbComp);
3553 double *vals=array->getPointer();
3554 const int *connI=_nodal_connec_index->getConstPointer();
3555 const int *conn=_nodal_connec->getConstPointer();
3556 const double *coords=_coords->getConstPointer();
3557 if(getMeshDimension()==2)
3559 if(getSpaceDimension()==3)
3561 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3562 const double *locPtr=loc->getConstPointer();
3563 for(int i=0;i<nbOfCells;i++,vals+=3)
3565 int offset=connI[i];
3566 INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3567 double n=INTERP_KERNEL::norm<3>(vals);
3568 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3573 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3574 const double *isAbsPtr=isAbs->getArray()->begin();
3575 for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3576 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3579 else//meshdimension==1
3582 for(int i=0;i<nbOfCells;i++)
3584 int offset=connI[i];
3585 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3586 double n=INTERP_KERNEL::norm<2>(tmp);
3587 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3592 ret->setArray(array);
3594 ret->synchronizeTimeWithSupport();
3599 * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3600 * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3601 * and are normalized.
3602 * <br> \a this can be either
3603 * - a 2D mesh in 2D or 3D space or
3604 * - an 1D mesh in 2D space.
3606 * This method avoids building explicitly a part of \a this mesh to perform the work.
3607 * \param [in] begin - an array of cell ids of interest.
3608 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3609 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3610 * cells and one time. The caller is to delete this field using decrRef() as
3611 * it is no more needed.
3612 * \throw If the nodal connectivity of cells is not defined.
3613 * \throw If the coordinates array is not set.
3614 * \throw If the mesh dimension is not set.
3615 * \throw If the mesh and space dimension is not as specified above.
3616 * \sa buildOrthogonalField()
3618 * \if ENABLE_EXAMPLES
3619 * \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3620 * \ref py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3623 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3625 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3626 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3627 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3628 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3629 std::size_t nbelems=std::distance(begin,end);
3630 int nbComp=getMeshDimension()+1;
3631 array->alloc((int)nbelems,nbComp);
3632 double *vals=array->getPointer();
3633 const int *connI=_nodal_connec_index->getConstPointer();
3634 const int *conn=_nodal_connec->getConstPointer();
3635 const double *coords=_coords->getConstPointer();
3636 if(getMeshDimension()==2)
3638 if(getSpaceDimension()==3)
3640 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3641 const double *locPtr=loc->getConstPointer();
3642 for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3644 int offset=connI[*i];
3645 INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3646 double n=INTERP_KERNEL::norm<3>(vals);
3647 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3652 for(std::size_t i=0;i<nbelems;i++)
3653 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3656 else//meshdimension==1
3659 for(const int *i=begin;i!=end;i++)
3661 int offset=connI[*i];
3662 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3663 double n=INTERP_KERNEL::norm<2>(tmp);
3664 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3669 ret->setArray(array);
3671 ret->synchronizeTimeWithSupport();
3676 * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3677 * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3678 * and are \b not normalized.
3679 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3680 * cells and one time. The caller is to delete this field using decrRef() as
3681 * it is no more needed.
3682 * \throw If the nodal connectivity of cells is not defined.
3683 * \throw If the coordinates array is not set.
3684 * \throw If \a this->getMeshDimension() != 1.
3685 * \throw If \a this mesh includes cells of type other than SEG2.
3687 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3689 if(getMeshDimension()!=1)
3690 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3691 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3692 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3693 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3694 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3695 int nbOfCells=getNumberOfCells();
3696 int spaceDim=getSpaceDimension();
3697 array->alloc(nbOfCells,spaceDim);
3698 double *pt=array->getPointer();
3699 const double *coo=getCoords()->getConstPointer();
3700 std::vector<int> conn;
3702 for(int i=0;i<nbOfCells;i++)
3705 getNodeIdsOfCell(i,conn);
3706 pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3708 ret->setArray(array);
3710 ret->synchronizeTimeWithSupport();
3715 * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3716 * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3717 * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3718 * from. If a result face is shared by two 3D cells, then the face in included twice in
3720 * \param [in] origin - 3 components of a point defining location of the plane.
3721 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3722 * must be greater than 1e-6.
3723 * \param [in] eps - half-thickness of the plane.
3724 * \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3725 * producing correspondent 2D cells. The caller is to delete this array
3726 * using decrRef() as it is no more needed.
3727 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3728 * not share the node coordinates array with \a this mesh. The caller is to
3729 * delete this mesh using decrRef() as it is no more needed.
3730 * \throw If the coordinates array is not set.
3731 * \throw If the nodal connectivity of cells is not defined.
3732 * \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3733 * \throw If magnitude of \a vec is less than 1e-6.
3734 * \throw If the plane does not intersect any 3D cell of \a this mesh.
3735 * \throw If \a this includes quadratic cells.
3737 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3739 checkFullyDefined();
3740 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3741 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3742 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3743 if(candidates->empty())
3744 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3745 std::vector<int> nodes;
3746 DataArrayInt *cellIds1D=0;
3747 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3748 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3749 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3750 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3751 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3752 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3753 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3754 revDesc2=0; revDescIndx2=0;
3755 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3756 revDesc1=0; revDescIndx1=0;
3757 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3758 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3760 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3761 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3763 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3764 std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3765 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3766 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3767 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3768 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3769 connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3770 subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3771 if(cellIds2->empty())
3772 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3773 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3774 ret->setCoords(mDesc1->getCoords());
3775 ret->setConnectivity(conn,connI,true);
3776 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3781 * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3782 addition to the mesh, returns a new DataArrayInt, of length equal to the number of 1D cells in the result mesh, holding, for each cell in the result mesh, an id of a 2D cell it comes
3783 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3785 * \param [in] origin - 3 components of a point defining location of the plane.
3786 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3787 * must be greater than 1e-6.
3788 * \param [in] eps - half-thickness of the plane.
3789 * \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3790 * producing correspondent segments. The caller is to delete this array
3791 * using decrRef() as it is no more needed.
3792 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3793 * mesh in 3D space. This mesh does not share the node coordinates array with
3794 * \a this mesh. The caller is to delete this mesh using decrRef() as it is
3796 * \throw If the coordinates array is not set.
3797 * \throw If the nodal connectivity of cells is not defined.
3798 * \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3799 * \throw If magnitude of \a vec is less than 1e-6.
3800 * \throw If the plane does not intersect any 2D cell of \a this mesh.
3801 * \throw If \a this includes quadratic cells.
3803 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3805 checkFullyDefined();
3806 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3807 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3808 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3809 if(candidates->empty())
3810 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3811 std::vector<int> nodes;
3812 DataArrayInt *cellIds1D=0;
3813 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3814 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3815 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3816 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3817 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3818 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3819 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3820 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3821 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3823 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3824 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3826 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3827 int ncellsSub=subMesh->getNumberOfCells();
3828 std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3829 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3830 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3831 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3832 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3834 const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3835 const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3836 for(int i=0;i<ncellsSub;i++)
3838 if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3840 if(cut3DSurf[i].first!=-2)
3842 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3843 connI->pushBackSilent(conn->getNumberOfTuples());
3844 cellIds2->pushBackSilent(i);
3848 int cellId3DSurf=cut3DSurf[i].second;
3849 int offset=nodalI[cellId3DSurf]+1;
3850 int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3851 for(int j=0;j<nbOfEdges;j++)
3853 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3854 connI->pushBackSilent(conn->getNumberOfTuples());
3855 cellIds2->pushBackSilent(cellId3DSurf);
3860 if(cellIds2->empty())
3861 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3862 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3863 ret->setCoords(mDesc1->getCoords());
3864 ret->setConnectivity(conn,connI,true);
3865 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3870 * Finds cells whose bounding boxes intersect a given plane.
3871 * \param [in] origin - 3 components of a point defining location of the plane.
3872 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3873 * must be greater than 1e-6.
3874 * \param [in] eps - half-thickness of the plane.
3875 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3876 * cells. The caller is to delete this array using decrRef() as it is no more
3878 * \throw If the coordinates array is not set.
3879 * \throw If the nodal connectivity of cells is not defined.
3880 * \throw If \a this->getSpaceDimension() != 3.
3881 * \throw If magnitude of \a vec is less than 1e-6.
3882 * \sa buildSlice3D()
3884 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3886 checkFullyDefined();
3887 if(getSpaceDimension()!=3)
3888 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3889 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3891 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3893 vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3894 double angle=acos(vec[2]/normm);
3895 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3899 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3900 double normm2(sqrt(vec2[0]*vec2[0]+vec2[1]*vec2[1]+vec2[2]*vec2[2]));
3901 if(normm2/normm>1e-6)
3902 MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3903 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3905 mw->getBoundingBox(bbox);
3906 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3907 cellIds=mw->getCellsInBoundingBox(bbox,eps);
3911 getBoundingBox(bbox);
3912 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3913 cellIds=getCellsInBoundingBox(bbox,eps);
3915 return cellIds.retn();
3919 * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3920 * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3921 * No consideration of coordinate is done by this method.
3922 * A 1D mesh is said contiguous if : a cell i with nodal connectivity (k,p) the cell i+1 the nodal connectivity should be (p,m)
3923 * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3925 bool MEDCouplingUMesh::isContiguous1D() const
3927 if(getMeshDimension()!=1)
3928 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3929 int nbCells=getNumberOfCells();
3931 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3932 const int *connI=_nodal_connec_index->getConstPointer();
3933 const int *conn=_nodal_connec->getConstPointer();
3934 int ref=conn[connI[0]+2];
3935 for(int i=1;i<nbCells;i++)
3937 if(conn[connI[i]+1]!=ref)
3939 ref=conn[connI[i]+2];
3945 * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3946 * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3947 * \param pt reference point of the line
3948 * \param v normalized director vector of the line
3949 * \param eps max precision before throwing an exception
3950 * \param res output of size this->getNumberOfCells
3952 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3954 if(getMeshDimension()!=1)
3955 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3956 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3957 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3958 if(getSpaceDimension()!=3)
3959 throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3960 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3961 const double *fPtr=f->getArray()->getConstPointer();
3963 for(int i=0;i<getNumberOfCells();i++)
3965 const double *tmp1=fPtr+3*i;
3966 tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3967 tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3968 tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3969 double n1=INTERP_KERNEL::norm<3>(tmp);
3970 n1/=INTERP_KERNEL::norm<3>(tmp1);
3972 throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3974 const double *coo=getCoords()->getConstPointer();
3975 for(int i=0;i<getNumberOfNodes();i++)
3977 std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3978 std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3979 res[i]=std::accumulate(tmp,tmp+3,0.);
3984 * This method computes the distance from a point \a pt to \a this and the first \a cellId in \a this corresponding to the returned distance.
3985 * \a this is expected to be a mesh so that its space dimension is equal to its
3986 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3987 * Distance from \a ptBg to \a ptEnd is expected to be equal to the space dimension. \a this is also expected to be fully defined (connectivity and coordinates).
3989 * WARNING, if there is some orphan nodes in \a this (nodes not fetched by any cells in \a this ( see MEDCouplingUMesh::zipCoords ) ) these nodes will ** not ** been taken
3990 * into account in this method. Only cells and nodes lying on them are considered in the algorithm (even if one of these orphan nodes is closer than returned distance).
3991 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3993 * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3994 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3996 * \param [in] ptBg the start pointer (included) of the coordinates of the point
3997 * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3998 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3999 * \return the positive value of the distance.
4000 * \throw if distance from \a ptBg to \a ptEnd is not equal to the space dimension. An exception is also thrown if mesh dimension of \a this is not equal to space
4002 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
4004 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
4006 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4007 if(meshDim!=spaceDim-1)
4008 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
4009 if(meshDim!=2 && meshDim!=1)
4010 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4011 checkFullyDefined();
4012 if((int)std::distance(ptBg,ptEnd)!=spaceDim)
4013 { std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoint : input point has to have dimension equal to the space dimension of this (" << spaceDim << ") !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
4014 DataArrayInt *ret1=0;
4015 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
4016 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
4017 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
4018 cellId=*ret1Safe->begin();
4019 return *ret0->begin();
4023 * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
4024 * to \a this and the first \a cellId in \a this corresponding to the returned distance.
4025 * WARNING, if there is some orphan nodes in \a this (nodes not fetched by any cells in \a this ( see MEDCouplingUMesh::zipCoords ) ) these nodes will ** not ** been taken
4026 * into account in this method. Only cells and nodes lying on them are considered in the algorithm (even if one of these orphan nodes is closer than returned distance).
4027 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4029 * \a this is expected to be a mesh so that its space dimension is equal to its
4030 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4031 * Number of components of \a pts is expected to be equal to the space dimension. \a this is also expected to be fully defined (connectivity and coordinates).
4033 * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
4034 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4036 * \param [in] pts the list of points in which each tuple represents a point
4037 * \param [out] cellIds a newly allocated object that tells for each point in \a pts the first cell id in \a this that minimizes the distance.
4038 * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
4039 * \throw if number of components of \a pts is not equal to the space dimension.
4040 * \throw if mesh dimension of \a this is not equal to space dimension - 1.
4041 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
4043 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
4046 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
4047 pts->checkAllocated();
4048 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4049 if(meshDim!=spaceDim-1)
4050 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
4051 if(meshDim!=2 && meshDim!=1)
4052 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
4053 if(pts->getNumberOfComponents()!=spaceDim)
4055 std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
4056 throw INTERP_KERNEL::Exception(oss.str().c_str());
4058 checkFullyDefined();
4059 int nbCells=getNumberOfCells();
4061 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4062 int nbOfPts=pts->getNumberOfTuples();
4063 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4064 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4065 const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4066 double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4067 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4068 const double *bbox(bboxArr->begin());
4073 BBTreeDst<3> myTree(bbox,0,0,nbCells);
4074 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4076 double x=std::numeric_limits<double>::max();
4077 std::vector<int> elems;
4078 myTree.getMinDistanceOfMax(ptsPtr,x);
4079 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4080 DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4086 BBTreeDst<2> myTree(bbox,0,0,nbCells);
4087 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4089 double x=std::numeric_limits<double>::max();
4090 std::vector<int> elems;
4091 myTree.getMinDistanceOfMax(ptsPtr,x);
4092 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4093 DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4098 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4100 cellIds=ret1.retn();
4105 * \param [in] pt the start pointer (included) of the coordinates of the point
4106 * \param [in] cellIdsBg the start pointer (included) of cellIds
4107 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4108 * \param [in] nc nodal connectivity
4109 * \param [in] ncI nodal connectivity index
4110 * \param [in,out] ret0 the min distance between \a this and the external input point
4111 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4112 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4114 void MEDCouplingUMesh::DistanceToPoint3DSurfAlg(const double *pt, const int *cellIdsBg, const int *cellIdsEnd, const double *coords, const int *nc, const int *ncI, double& ret0, int& cellId)
4117 ret0=std::numeric_limits<double>::max();
4118 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4120 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4122 case INTERP_KERNEL::NORM_TRI3:
4124 double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4126 { ret0=tmp; cellId=*zeCell; }
4129 case INTERP_KERNEL::NORM_QUAD4:
4130 case INTERP_KERNEL::NORM_POLYGON:
4132 double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4134 { ret0=tmp; cellId=*zeCell; }
4138 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4144 * \param [in] pt the start pointer (included) of the coordinates of the point
4145 * \param [in] cellIdsBg the start pointer (included) of cellIds
4146 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4147 * \param [in] nc nodal connectivity
4148 * \param [in] ncI nodal connectivity index
4149 * \param [in,out] ret0 the min distance between \a this and the external input point
4150 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4151 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4153 void MEDCouplingUMesh::DistanceToPoint2DCurveAlg(const double *pt, const int *cellIdsBg, const int *cellIdsEnd, const double *coords, const int *nc, const int *ncI, double& ret0, int& cellId)
4156 ret0=std::numeric_limits<double>::max();
4157 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4159 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4161 case INTERP_KERNEL::NORM_SEG2:
4163 std::size_t uselessEntry=0;
4164 double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4167 { ret0=tmp; cellId=*zeCell; }
4171 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4177 * Finds cells in contact with a ball (i.e. a point with precision).
4178 * For speed reasons, the INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6 and INTERP_KERNEL::NORM_QUAD8 cells are considered as convex cells to detect if a point is IN or OUT.
4179 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4181 * \warning This method is suitable if the caller intends to evaluate only one
4182 * point, for more points getCellsContainingPoints() is recommended as it is
4184 * \param [in] pos - array of coordinates of the ball central point.
4185 * \param [in] eps - ball radius.
4186 * \return int - a smallest id of cells being in contact with the ball, -1 in case
4187 * if there are no such cells.
4188 * \throw If the coordinates array is not set.
4189 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4191 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4193 std::vector<int> elts;
4194 getCellsContainingPoint(pos,eps,elts);
4197 return elts.front();
4201 * Finds cells in contact with a ball (i.e. a point with precision).
4202 * For speed reasons, the INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6 and INTERP_KERNEL::NORM_QUAD8 cells are considered as convex cells to detect if a point is IN or OUT.
4203 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4204 * \warning This method is suitable if the caller intends to evaluate only one
4205 * point, for more points getCellsContainingPoints() is recommended as it is
4207 * \param [in] pos - array of coordinates of the ball central point.
4208 * \param [in] eps - ball radius.
4209 * \param [out] elts - vector returning ids of the found cells. It is cleared
4210 * before inserting ids.
4211 * \throw If the coordinates array is not set.
4212 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4214 * \if ENABLE_EXAMPLES
4215 * \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4216 * \ref py_mcumesh_getCellsContainingPoint "Here is a Python example".
4219 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4221 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4222 getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4223 elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4228 namespace ParaMEDMEM
4230 template<const int SPACEDIMM>
4234 static const int MY_SPACEDIM=SPACEDIMM;
4235 static const int MY_MESHDIM=8;
4236 typedef int MyConnType;
4237 static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4239 // useless, but for windows compilation ...
4240 const double* getCoordinatesPtr() const { return 0; }
4241 const int* getConnectivityPtr() const { return 0; }
4242 const int* getConnectivityIndexPtr() const { return 0; }
4243 INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4247 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m)
4249 INTERP_KERNEL::Edge *ret(0);
4250 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> n0(new INTERP_KERNEL::Node(coords2D[2*bg[0]],coords2D[2*bg[0]+1])),n1(new INTERP_KERNEL::Node(coords2D[2*bg[1]],coords2D[2*bg[1]+1]));
4251 m[n0]=bg[0]; m[n1]=bg[1];
4254 case INTERP_KERNEL::NORM_SEG2:
4256 ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4259 case INTERP_KERNEL::NORM_SEG3:
4261 INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4262 INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4263 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4264 // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4265 bool colinearity(inters.areColinears());
4266 delete e1; delete e2;
4268 { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4270 { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4274 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4279 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4281 INTERP_KERNEL::Edge *ret=0;
4284 case INTERP_KERNEL::NORM_SEG2:
4286 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4289 case INTERP_KERNEL::NORM_SEG3:
4291 INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4292 INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4293 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4294 // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4295 bool colinearity=inters.areColinears();
4296 delete e1; delete e2;
4298 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4300 ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4301 mapp2[bg[2]].second=false;
4305 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4311 * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4312 * the global mesh 'mDesc'.
4313 * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4314 * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4316 INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4317 std::map<INTERP_KERNEL::Node *,int>& mapp)
4320 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;//bool is for a flag specifying if node is boundary (true) or only a middle for SEG3.
4321 const double *coo=mDesc->getCoords()->getConstPointer();
4322 const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4323 const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4325 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4326 s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4327 for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4329 INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4330 mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4332 INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4333 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4335 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4336 ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4338 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4340 if((*it2).second.second)
4341 mapp[(*it2).second.first]=(*it2).first;
4342 ((*it2).second.first)->decrRef();
4347 INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4351 int locId=nodeId-offset2;
4352 return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4356 int locId=nodeId-offset1;
4357 return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4359 return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4363 * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4365 void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4366 const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4367 /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4369 for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4371 int eltId1=abs(*desc1)-1;
4372 for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4374 std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4375 if(it==mappRev.end())
4377 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4388 template<int SPACEDIM>
4389 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4390 double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4392 elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4393 int *eltsIndexPtr(eltsIndex->getPointer());
4394 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4395 const double *bbox(bboxArr->begin());
4396 int nbOfCells=getNumberOfCells();
4397 const int *conn=_nodal_connec->getConstPointer();
4398 const int *connI=_nodal_connec_index->getConstPointer();
4399 double bb[2*SPACEDIM];
4400 BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4401 for(int i=0;i<nbOfPoints;i++)
4403 eltsIndexPtr[i+1]=eltsIndexPtr[i];
4404 for(int j=0;j<SPACEDIM;j++)
4406 bb[2*j]=pos[SPACEDIM*i+j];
4407 bb[2*j+1]=pos[SPACEDIM*i+j];
4409 std::vector<int> candidates;
4410 myTree.getIntersectingElems(bb,candidates);
4411 for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4413 int sz(connI[(*iter)+1]-connI[*iter]-1);
4414 INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4416 if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4417 status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4421 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4422 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4423 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4424 std::vector<INTERP_KERNEL::Node *> nodes(sz);
4425 INTERP_KERNEL::QuadraticPolygon *pol(0);
4426 for(int j=0;j<sz;j++)
4428 int nodeId(conn[connI[*iter]+1+j]);
4429 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4431 if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4432 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4434 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4435 INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4436 double a(0.),b(0.),c(0.);
4437 a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4438 status=pol->isInOrOut2(n);
4439 delete pol; n->decrRef();
4443 eltsIndexPtr[i+1]++;
4444 elts->pushBackSilent(*iter);
4450 * Finds cells in contact with several balls (i.e. points with precision).
4451 * This method is an extension of getCellContainingPoint() and
4452 * getCellsContainingPoint() for the case of multiple points.
4453 * For speed reasons, the INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6 and INTERP_KERNEL::NORM_QUAD8 cells are considered as convex cells to detect if a point is IN or OUT.
4454 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4455 * \param [in] pos - an array of coordinates of points in full interlace mode :
4456 * X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4457 * this->getSpaceDimension() * \a nbOfPoints
4458 * \param [in] nbOfPoints - number of points to locate within \a this mesh.
4459 * \param [in] eps - radius of balls (i.e. the precision).
4460 * \param [out] elts - vector returning ids of found cells.
4461 * \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4462 * dividing cell ids in \a elts into groups each referring to one
4463 * point. Its every element (except the last one) is an index pointing to the
4464 * first id of a group of cells. For example cells in contact with the *i*-th
4465 * point are described by following range of indices:
4466 * [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4467 * \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4468 * Number of cells in contact with the *i*-th point is
4469 * \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4470 * \throw If the coordinates array is not set.
4471 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4473 * \if ENABLE_EXAMPLES
4474 * \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4475 * \ref py_mcumesh_getCellsContainingPoints "Here is a Python example".
4478 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4479 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4481 int spaceDim=getSpaceDimension();
4482 int mDim=getMeshDimension();
4487 const double *coords=_coords->getConstPointer();
4488 getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4495 throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4497 else if(spaceDim==2)
4501 const double *coords=_coords->getConstPointer();
4502 getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4505 throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4507 else if(spaceDim==1)
4511 const double *coords=_coords->getConstPointer();
4512 getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4515 throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4518 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4522 * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4523 * least two its edges intersect each other anywhere except their extremities. An
4524 * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4525 * \param [in,out] cells - a vector returning ids of the found cells. It is not
4526 * cleared before filling in.
4527 * \param [in] eps - precision.
4528 * \throw If \a this->getMeshDimension() != 2.
4529 * \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4531 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4533 const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4534 if(getMeshDimension()!=2)
4535 throw INTERP_KERNEL::Exception(msg);
4536 int spaceDim=getSpaceDimension();
4537 if(spaceDim!=2 && spaceDim!=3)
4538 throw INTERP_KERNEL::Exception(msg);
4539 const int *conn=_nodal_connec->getConstPointer();
4540 const int *connI=_nodal_connec_index->getConstPointer();
4541 int nbOfCells=getNumberOfCells();
4542 std::vector<double> cell2DinS2;
4543 for(int i=0;i<nbOfCells;i++)
4545 int offset=connI[i];
4546 int nbOfNodesForCell=connI[i+1]-offset-1;
4547 if(nbOfNodesForCell<=3)
4549 bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4550 project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4551 if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4558 * This method is typically requested to unbutterfly 2D linear cells in \b this.
4560 * This method expects that space dimension is equal to 2 and mesh dimension is equal to 2 too. If it is not the case an INTERP_KERNEL::Exception will be thrown.
4561 * This method works only for linear 2D cells. If there is any of non linear cells (INTERP_KERNEL::NORM_QUAD8 for example) an INTERP_KERNEL::Exception will be thrown too.
4563 * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4564 * This convex envelop is computed using Jarvis march algorithm.
4565 * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4566 * Only connectivity of some cells could be modified if those cells were not representing a convex envelop. If a cell already equals its convex envelop (regardless orientation)
4567 * its connectivity will remain unchanged. If the computation leads to a modification of nodal connectivity of a cell its geometric type will be modified to INTERP_KERNEL::NORM_POLYGON.
4569 * \return a newly allocated array containing cellIds that have been modified if any. If no cells have been impacted by this method NULL is returned.
4570 * \sa MEDCouplingUMesh::colinearize2D
4572 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4574 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4575 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D works only for meshDim=2 and spaceDim=2 !");
4576 checkFullyDefined();
4577 const double *coords=getCoords()->getConstPointer();
4578 int nbOfCells=getNumberOfCells();
4579 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4580 nodalConnecIndexOut->alloc(nbOfCells+1,1);
4581 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4582 int *workIndexOut=nodalConnecIndexOut->getPointer();
4584 const int *nodalConnecIn=_nodal_connec->getConstPointer();
4585 const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4586 std::set<INTERP_KERNEL::NormalizedCellType> types;
4587 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4588 isChanged->alloc(0,1);
4589 for(int i=0;i<nbOfCells;i++,workIndexOut++)
4591 int pos=nodalConnecOut->getNumberOfTuples();
4592 if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4593 isChanged->pushBackSilent(i);
4594 types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4595 workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4597 if(isChanged->empty())
4599 setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4601 return isChanged.retn();
4605 * This method is \b NOT const because it can modify \a this.
4606 * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4607 * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4608 * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4609 * \b 1 for translation and rotation around point of 'mesh1D'.
4610 * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.
4612 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4614 checkFullyDefined();
4615 mesh1D->checkFullyDefined();
4616 if(!mesh1D->isContiguous1D())
4617 throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4618 if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4619 throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4620 if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4621 throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4622 if(mesh1D->getMeshDimension()!=1)
4623 throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4625 if(isPresenceOfQuadratic())
4627 if(mesh1D->isFullyQuadratic())
4630 throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4632 int oldNbOfNodes(getNumberOfNodes());
4633 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4638 newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4643 newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4647 throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4649 setCoords(newCoords);
4650 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad));
4656 * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4657 * If it is not the case an exception will be thrown.
4658 * This method is non const because the coordinate of \a this can be appended with some new points issued from
4659 * intersection of plane defined by ('origin','vec').
4660 * This method has one in/out parameter : 'cut3DCurve'.
4661 * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4662 * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4663 * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4664 * This method will throw an exception if \a this contains a non linear segment.
4666 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4668 checkFullyDefined();
4669 if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4670 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4671 int ncells=getNumberOfCells();
4672 int nnodes=getNumberOfNodes();
4673 double vec2[3],vec3[3],vec4[3];
4674 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4676 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4677 vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4678 const int *conn=_nodal_connec->getConstPointer();
4679 const int *connI=_nodal_connec_index->getConstPointer();
4680 const double *coo=_coords->getConstPointer();
4681 std::vector<double> addCoo;
4682 for(int i=0;i<ncells;i++)
4684 if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4686 if(cut3DCurve[i]==-2)
4688 int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4689 vec3[0]=coo[3*endd]-coo[3*st]; vec3[1]=coo[3*endd+1]-coo[3*st+1]; vec3[2]=coo[3*endd+2]-coo[3*st+2];
4690 double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4691 double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4692 if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4694 const double *st2=coo+3*st;
4695 vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4696 double pos=-(vec4[0]*vec2[0]+vec4[1]*vec2[1]+vec4[2]*vec2[2])/((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2]));
4697 if(pos>eps && pos<1-eps)
4699 int nNode=((int)addCoo.size())/3;
4700 vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4701 addCoo.insert(addCoo.end(),vec4,vec4+3);
4702 cut3DCurve[i]=nnodes+nNode;
4708 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4712 int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4713 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4714 coo2->alloc(newNbOfNodes,3);
4715 double *tmp=coo2->getPointer();
4716 tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4717 std::copy(addCoo.begin(),addCoo.end(),tmp);
4718 DataArrayDouble::SetArrayIn(coo2,_coords);
4723 * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4724 * \param mesh1D is the input 1D mesh used for translation computation.
4725 * \return newCoords new coords filled by this method.
4727 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4729 int oldNbOfNodes=getNumberOfNodes();
4730 int nbOf1DCells=mesh1D->getNumberOfCells();
4731 int spaceDim=getSpaceDimension();
4732 DataArrayDouble *ret=DataArrayDouble::New();
4733 std::vector<bool> isQuads;
4734 int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4735 ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4736 double *retPtr=ret->getPointer();
4737 const double *coords=getCoords()->getConstPointer();
4738 double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4740 std::vector<double> c;
4744 for(int i=0;i<nbOf1DCells;i++)
4747 mesh1D->getNodeIdsOfCell(i,v);
4749 mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4750 mesh1D->getCoordinatesOfNode(v[0],c);
4751 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4752 for(int j=0;j<oldNbOfNodes;j++)
4753 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4757 mesh1D->getCoordinatesOfNode(v[1],c);
4758 mesh1D->getCoordinatesOfNode(v[0],c);
4759 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4760 for(int j=0;j<oldNbOfNodes;j++)
4761 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4764 ret->copyStringInfoFrom(*getCoords());
4769 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4770 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4771 * \return newCoords new coords filled by this method.
4773 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4775 if(mesh1D->getSpaceDimension()==2)
4776 return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4777 if(mesh1D->getSpaceDimension()==3)
4778 return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4779 throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4783 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4784 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4785 * \return newCoords new coords filled by this method.
4787 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4790 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4791 int oldNbOfNodes=getNumberOfNodes();
4792 int nbOf1DCells=mesh1D->getNumberOfCells();
4794 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4795 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4796 int nbOfLevsInVec=nbOf1DCells+1;
4797 ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4798 double *retPtr=ret->getPointer();
4799 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4800 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4801 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4802 tmp->setCoords(tmp2);
4803 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4804 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4805 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4806 for(int i=1;i<nbOfLevsInVec;i++)
4808 const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4809 const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4810 const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4811 const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4812 tmp->translate(vec);
4813 double tmp3[2],radius,alpha,alpha0;
4814 const double *p0=i+1<nbOfLevsInVec?begin:third;
4815 const double *p1=i+1<nbOfLevsInVec?end:begin;
4816 const double *p2=i+1<nbOfLevsInVec?third:end;
4817 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4818 double cosangle=i+1<nbOfLevsInVec?(p0[0]-tmp3[0])*(p1[0]-tmp3[0])+(p0[1]-tmp3[1])*(p1[1]-tmp3[1]):(p2[0]-tmp3[0])*(p1[0]-tmp3[0])+(p2[1]-tmp3[1])*(p1[1]-tmp3[1]);
4819 double angle=acos(cosangle/(radius*radius));
4820 tmp->rotate(end,0,angle);
4821 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4827 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4828 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4829 * \return newCoords new coords filled by this method.
4831 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4834 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4835 int oldNbOfNodes=getNumberOfNodes();
4836 int nbOf1DCells=mesh1D->getNumberOfCells();
4838 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4839 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4840 int nbOfLevsInVec=nbOf1DCells+1;
4841 ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4842 double *retPtr=ret->getPointer();
4843 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4844 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4845 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4846 tmp->setCoords(tmp2);
4847 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4848 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4849 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4850 for(int i=1;i<nbOfLevsInVec;i++)
4852 const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4853 const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4854 const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4855 const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4856 tmp->translate(vec);
4857 double tmp3[2],radius,alpha,alpha0;
4858 const double *p0=i+1<nbOfLevsInVec?begin:third;
4859 const double *p1=i+1<nbOfLevsInVec?end:begin;
4860 const double *p2=i+1<nbOfLevsInVec?third:end;
4861 double vecPlane[3]={
4862 (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4863 (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4864 (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4866 double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4869 vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4870 double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4871 double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4873 double c2=cos(asin(s2));
4875 {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4876 {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4877 {-vec2[1]*s2, vec2[0]*s2, c2}
4879 double p0r[3]={m[0][0]*p0[0]+m[0][1]*p0[1]+m[0][2]*p0[2], m[1][0]*p0[0]+m[1][1]*p0[1]+m[1][2]*p0[2], m[2][0]*p0[0]+m[2][1]*p0[1]+m[2][2]*p0[2]};
4880 double p1r[3]={m[0][0]*p1[0]+m[0][1]*p1[1]+m[0][2]*p1[2], m[1][0]*p1[0]+m[1][1]*p1[1]+m[1][2]*p1[2], m[2][0]*p1[0]+m[2][1]*p1[1]+m[2][2]*p1[2]};
4881 double p2r[3]={m[0][0]*p2[0]+m[0][1]*p2[1]+m[0][2]*p2[2], m[1][0]*p2[0]+m[1][1]*p2[1]+m[1][2]*p2[2], m[2][0]*p2[0]+m[2][1]*p2[1]+m[2][2]*p2[2]};
4882 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4883 double cosangle=i+1<nbOfLevsInVec?(p0r[0]-tmp3[0])*(p1r[0]-tmp3[0])+(p0r[1]-tmp3[1])*(p1r[1]-tmp3[1]):(p2r[0]-tmp3[0])*(p1r[0]-tmp3[0])+(p2r[1]-tmp3[1])*(p1r[1]-tmp3[1]);
4884 double angle=acos(cosangle/(radius*radius));
4885 tmp->rotate(end,vecPlane,angle);
4887 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4893 * This method is private because not easy to use for end user. This method is const contrary to
4894 * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4895 * the coords sorted slice by slice.
4896 * \param isQuad specifies presence of quadratic cells.
4898 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4900 int nbOf1DCells(getNumberOfNodes()/nbOfNodesOf1Lev-1);
4901 int nbOf2DCells(getNumberOfCells());
4902 int nbOf3DCells(nbOf2DCells*nbOf1DCells);
4903 MEDCouplingUMesh *ret(MEDCouplingUMesh::New("Extruded",getMeshDimension()+1));
4904 const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
4905 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()),newConnI(DataArrayInt::New());
4906 newConnI->alloc(nbOf3DCells+1,1);
4907 int *newConnIPtr(newConnI->getPointer());
4909 std::vector<int> newc;
4910 for(int j=0;j<nbOf2DCells;j++)
4912 AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4913 *newConnIPtr++=(int)newc.size();
4915 newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4916 int *newConnPtr(newConn->getPointer());
4917 int deltaPerLev(isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev);
4918 newConnIPtr=newConnI->getPointer();
4919 for(int iz=0;iz<nbOf1DCells;iz++)
4922 std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4923 const int *posOfTypeOfCell(newConnIPtr);
4924 for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4926 int icell((int)(iter-newc.begin()));//std::distance unfortunately cannot been called here in C++98
4927 if(icell!=*posOfTypeOfCell)
4930 *newConnPtr=(*iter)+iz*deltaPerLev;
4941 ret->setConnectivity(newConn,newConnI,true);
4942 ret->setCoords(getCoords());
4947 * Checks if \a this mesh is constituted by only quadratic cells.
4948 * \return bool - \c true if there are only quadratic cells in \a this mesh.
4949 * \throw If the coordinates array is not set.
4950 * \throw If the nodal connectivity of cells is not defined.
4952 bool MEDCouplingUMesh::isFullyQuadratic() const
4954 checkFullyDefined();
4956 int nbOfCells=getNumberOfCells();
4957 for(int i=0;i<nbOfCells && ret;i++)
4959 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4960 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4961 ret=cm.isQuadratic();
4967 * Checks if \a this mesh includes any quadratic cell.
4968 * \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4969 * \throw If the coordinates array is not set.
4970 * \throw If the nodal connectivity of cells is not defined.
4972 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4974 checkFullyDefined();
4976 int nbOfCells=getNumberOfCells();
4977 for(int i=0;i<nbOfCells && !ret;i++)
4979 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4980 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4981 ret=cm.isQuadratic();
4987 * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4988 * this mesh, it remains unchanged.
4989 * \throw If the coordinates array is not set.
4990 * \throw If the nodal connectivity of cells is not defined.
4992 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4994 checkFullyDefined();
4995 int nbOfCells=getNumberOfCells();
4997 const int *iciptr=_nodal_connec_index->getConstPointer();
4998 for(int i=0;i<nbOfCells;i++)
5000 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5001 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5002 if(cm.isQuadratic())
5004 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5005 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5006 if(!cml.isDynamic())
5007 delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
5009 delta+=(iciptr[i+1]-iciptr[i]-1)/2;
5014 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5015 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5016 const int *icptr=_nodal_connec->getConstPointer();
5017 newConn->alloc(getMeshLength()-delta,1);
5018 newConnI->alloc(nbOfCells+1,1);
5019 int *ocptr=newConn->getPointer();
5020 int *ociptr=newConnI->getPointer();
5023 for(int i=0;i<nbOfCells;i++,ociptr++)
5025 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
5026 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5027 if(!cm.isQuadratic())
5029 _types.insert(type);
5030 ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5031 ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5035 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5036 _types.insert(typel);
5037 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5038 int newNbOfNodes=cml.getNumberOfNodes();
5040 newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
5041 *ocptr++=(int)typel;
5042 ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5043 ociptr[1]=ociptr[0]+newNbOfNodes+1;
5046 setConnectivity(newConn,newConnI,false);
5050 * This method converts all linear cell in \a this to quadratic one.
5051 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5052 * type of cells expected. For example INTERP_KERNEL::NORM_TRI3 can be converted to INTERP_KERNEL::NORM_TRI6 if \a conversionType is equal to 0 (the default)
5053 * or to INTERP_KERNEL::NORM_TRI7 if \a conversionType is equal to 1. All non linear cells and polyhedron in \a this are let untouched.
5054 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5055 * end of the existing coordinates.
5057 * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5058 * corresponding quadratic cells. 1 is those creating the 'most' complex.
5059 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5061 * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5063 * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5065 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5067 DataArrayInt *conn=0,*connI=0;
5068 DataArrayDouble *coords=0;
5069 std::set<INTERP_KERNEL::NormalizedCellType> types;
5070 checkFullyDefined();
5071 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5072 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5073 int meshDim=getMeshDimension();
5074 switch(conversionType)
5080 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5081 connSafe=conn; connISafe=connI; coordsSafe=coords;
5084 ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5085 connSafe=conn; connISafe=connI; coordsSafe=coords;
5088 ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5089 connSafe=conn; connISafe=connI; coordsSafe=coords;
5092 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5100 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5101 connSafe=conn; connISafe=connI; coordsSafe=coords;
5104 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5105 connSafe=conn; connISafe=connI; coordsSafe=coords;
5108 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5109 connSafe=conn; connISafe=connI; coordsSafe=coords;
5112 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5117 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5119 setConnectivity(connSafe,connISafe,false);
5121 setCoords(coordsSafe);
5127 * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
5128 * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
5129 * The nodes to be added in those 2D cells are defined by the pair of \a nodeIdsToAdd and \a nodeIdsIndexToAdd.
5130 * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
5131 * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
5132 * This method can be seen as the opposite method of colinearize2D.
5133 * This method can be lead to create some new nodes if quadratic polygon cells have to be split. In this case the added nodes will be put at the end
5134 * to avoid to modify the numbering of existing nodes.
5136 * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
5137 * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
5138 * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
5139 * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
5140 * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
5141 * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
5142 * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
5144 * \sa buildDescendingConnectivity2
5146 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
5147 const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
5149 if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
5150 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
5151 nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
5152 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
5153 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
5154 if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
5155 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
5156 //DataArrayInt *out0(0),*outi0(0);
5157 //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
5158 //MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s(out0),outi0s(outi0);
5159 //out0s=out0s->buildUnique(); out0s->sort(true);
5164 * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5165 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5166 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5168 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5170 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5171 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5172 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5173 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5174 int nbOfCells=getNumberOfCells();
5175 int nbOfNodes=getNumberOfNodes();
5176 const int *cPtr=_nodal_connec->getConstPointer();
5177 const int *icPtr=_nodal_connec_index->getConstPointer();
5178 int lastVal=0,offset=nbOfNodes;
5179 for(int i=0;i<nbOfCells;i++,icPtr++)
5181 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5182 if(type==INTERP_KERNEL::NORM_SEG2)
5184 types.insert(INTERP_KERNEL::NORM_SEG3);
5185 newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5186 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5187 newConn->pushBackSilent(offset++);
5189 newConnI->pushBackSilent(lastVal);
5190 ret->pushBackSilent(i);
5195 lastVal+=(icPtr[1]-icPtr[0]);
5196 newConnI->pushBackSilent(lastVal);
5197 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5200 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5201 coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5205 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2DAnd3D0(const MEDCouplingUMesh *m1D, const DataArrayInt *desc, const DataArrayInt *descI, DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5207 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5208 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5209 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5211 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5212 DataArrayInt *conn1D=0,*conn1DI=0;
5213 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5214 DataArrayDouble *coordsTmp=0;
5215 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5216 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5217 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5218 const int *c1DPtr=conn1D->begin();
5219 const int *c1DIPtr=conn1DI->begin();
5220 int nbOfCells=getNumberOfCells();
5221 const int *cPtr=_nodal_connec->getConstPointer();
5222 const int *icPtr=_nodal_connec_index->getConstPointer();
5224 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5226 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5227 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5228 if(!cm.isQuadratic())
5230 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5231 types.insert(typ2); newConn->pushBackSilent(typ2);
5232 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5233 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5234 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5235 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5236 newConnI->pushBackSilent(lastVal);
5237 ret->pushBackSilent(i);
5242 lastVal+=(icPtr[1]-icPtr[0]);
5243 newConnI->pushBackSilent(lastVal);
5244 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5247 conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5252 * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5253 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5254 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5256 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5258 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5259 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5260 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5263 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5265 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5266 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5268 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5269 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5270 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5272 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5273 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5274 DataArrayInt *conn1D=0,*conn1DI=0;
5275 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5276 DataArrayDouble *coordsTmp=0;
5277 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5278 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5279 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5280 const int *c1DPtr=conn1D->begin();
5281 const int *c1DIPtr=conn1DI->begin();
5282 int nbOfCells=getNumberOfCells();
5283 const int *cPtr=_nodal_connec->getConstPointer();
5284 const int *icPtr=_nodal_connec_index->getConstPointer();
5285 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5286 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5288 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5289 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5290 if(!cm.isQuadratic())
5292 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5293 types.insert(typ2); newConn->pushBackSilent(typ2);
5294 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5295 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5296 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5297 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5298 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5299 newConnI->pushBackSilent(lastVal);
5300 ret->pushBackSilent(i);
5305 lastVal+=(icPtr[1]-icPtr[0]);
5306 newConnI->pushBackSilent(lastVal);
5307 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5310 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5311 coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5316 * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5317 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5318 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5320 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5322 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5323 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5324 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5327 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5329 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5330 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5331 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5332 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5334 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5335 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5336 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5338 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5339 const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5340 DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5341 std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5342 DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5343 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5344 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5345 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5346 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5347 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5348 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5349 const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5350 int nbOfCells=getNumberOfCells();
5351 const int *cPtr=_nodal_connec->getConstPointer();
5352 const int *icPtr=_nodal_connec_index->getConstPointer();
5353 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5354 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5356 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5357 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5358 if(!cm.isQuadratic())
5360 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5361 if(typ2==INTERP_KERNEL::NORM_ERROR)
5363 std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5364 throw INTERP_KERNEL::Exception(oss.str().c_str());
5366 types.insert(typ2); newConn->pushBackSilent(typ2);
5367 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5368 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5369 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5370 for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5372 int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5373 int tmpPos=newConn->getNumberOfTuples();
5374 newConn->pushBackSilent(nodeId2);
5375 ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5377 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5378 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5379 newConnI->pushBackSilent(lastVal);
5380 ret->pushBackSilent(i);
5385 lastVal+=(icPtr[1]-icPtr[0]);
5386 newConnI->pushBackSilent(lastVal);
5387 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5390 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5391 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5392 coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5393 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5394 std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5395 int *c=newConn->getPointer();
5396 const int *cI(newConnI->begin());
5397 for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5398 c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5399 offset=coordsTmp2Safe->getNumberOfTuples();
5400 for(const int *elt=ret->begin();elt!=ret->end();elt++)
5401 c[cI[(*elt)+1]-1]+=offset;
5402 coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5407 * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5408 * so that the number of cells remains the same. Quadratic faces are converted to
5409 * polygons. This method works only for 2D meshes in
5410 * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5411 * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5412 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5413 * \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5414 * a polylinized edge constituting the input polygon.
5415 * \throw If the coordinates array is not set.
5416 * \throw If the nodal connectivity of cells is not defined.
5417 * \throw If \a this->getMeshDimension() != 2.
5418 * \throw If \a this->getSpaceDimension() != 2.
5420 void MEDCouplingUMesh::tessellate2D(double eps)
5422 checkFullyDefined();
5423 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
5424 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5425 double epsa=fabs(eps);
5426 if(epsa<std::numeric_limits<double>::min())
5427 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve : epsilon is null ! Please specify a higher epsilon. If too tiny it can lead to a huge amount of nodes and memory !");
5428 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5429 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5430 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5431 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5432 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5433 revDesc1=0; revDescIndx1=0;
5434 mDesc->tessellate2DCurve(eps);
5435 subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5436 setCoords(mDesc->getCoords());
5440 * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5441 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5442 * \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5443 * a sub-divided edge.
5444 * \throw If the coordinates array is not set.
5445 * \throw If the nodal connectivity of cells is not defined.
5446 * \throw If \a this->getMeshDimension() != 1.
5447 * \throw If \a this->getSpaceDimension() != 2.
5449 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5451 checkFullyDefined();
5452 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5453 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5454 double epsa=fabs(eps);
5455 if(epsa<std::numeric_limits<double>::min())
5456 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve : epsilon is null ! Please specify a higher epsilon. If too tiny it can lead to a huge amount of nodes and memory !");
5457 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5458 int nbCells=getNumberOfCells();
5459 int nbNodes=getNumberOfNodes();
5460 const int *conn=_nodal_connec->getConstPointer();
5461 const int *connI=_nodal_connec_index->getConstPointer();
5462 const double *coords=_coords->getConstPointer();
5463 std::vector<double> addCoo;
5464 std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5465 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5466 newConnI->alloc(nbCells+1,1);
5467 int *newConnIPtr=newConnI->getPointer();
5470 INTERP_KERNEL::Node *tmp2[3];
5471 std::set<INTERP_KERNEL::NormalizedCellType> types;
5472 for(int i=0;i<nbCells;i++,newConnIPtr++)
5474 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5475 if(cm.isQuadratic())
5476 {//assert(connI[i+1]-connI[i]-1==3)
5477 tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5478 tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5479 tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5480 tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5481 INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5484 eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5485 types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5487 newConnIPtr[1]=(int)newConn.size();
5491 types.insert(INTERP_KERNEL::NORM_SEG2);
5492 newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5493 newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5494 newConnIPtr[1]=newConnIPtr[0]+3;
5499 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5500 newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5501 newConnIPtr[1]=newConnIPtr[0]+3;
5504 if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5507 DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5508 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5509 newConnArr->alloc((int)newConn.size(),1);
5510 std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5511 DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5512 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5513 newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5514 double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5515 std::copy(addCoo.begin(),addCoo.end(),work);
5516 DataArrayDouble::SetArrayIn(newCoords,_coords);
5521 * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5522 * In addition, returns an array mapping new cells to old ones. <br>
5523 * This method typically increases the number of cells in \a this mesh
5524 * but the number of nodes remains \b unchanged.
5525 * That's why the 3D splitting policies
5526 * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5527 * \param [in] policy - specifies a pattern used for splitting.
5528 * The semantic of \a policy is:
5529 * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5530 * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5531 * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8 into 5 TETRA4 (for 3D mesh only).
5532 * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8 into 6 TETRA4 (for 3D mesh only).
5533 * \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5534 * an id of old cell producing it. The caller is to delete this array using
5535 * decrRef() as it is no more needed.
5536 * \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5537 * \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5538 * and \a this->getMeshDimension() != 3.
5539 * \throw If \a policy is not one of the four discussed above.
5540 * \throw If the nodal connectivity of cells is not defined.
5541 * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5543 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5548 return simplexizePol0();
5550 return simplexizePol1();
5551 case (int) INTERP_KERNEL::PLANAR_FACE_5:
5552 return simplexizePlanarFace5();
5553 case (int) INTERP_KERNEL::PLANAR_FACE_6:
5554 return simplexizePlanarFace6();
5556 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexize : unrecognized policy ! Must be :\n - 0 or 1 (only available for meshdim=2) \n - PLANAR_FACE_5, PLANAR_FACE_6 (only for meshdim=3)");
5561 * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5562 * - 1D: INTERP_KERNEL::NORM_SEG2
5563 * - 2D: INTERP_KERNEL::NORM_TRI3
5564 * - 3D: INTERP_KERNEL::NORM_TETRA4.
5566 * This method is useful for users that need to use P1 field services as
5567 * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5568 * All these methods need mesh support containing only simplex cells.
5569 * \return bool - \c true if there are only simplex cells in \a this mesh.
5570 * \throw If the coordinates array is not set.
5571 * \throw If the nodal connectivity of cells is not defined.
5572 * \throw If \a this->getMeshDimension() < 1.
5574 bool MEDCouplingUMesh::areOnlySimplexCells() const
5576 checkFullyDefined();
5577 int mdim=getMeshDimension();
5578 if(mdim<1 || mdim>3)
5579 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5580 int nbCells=getNumberOfCells();
5581 const int *conn=_nodal_connec->getConstPointer();
5582 const int *connI=_nodal_connec_index->getConstPointer();
5583 for(int i=0;i<nbCells;i++)
5585 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5593 * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5595 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5597 checkConnectivityFullyDefined();
5598 if(getMeshDimension()!=2)
5599 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5600 int nbOfCells=getNumberOfCells();
5601 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5602 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5603 ret->alloc(nbOfCells+nbOfCutCells,1);
5604 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5605 int *retPt=ret->getPointer();
5606 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5607 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5608 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5609 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5610 int *pt=newConn->getPointer();
5611 int *ptI=newConnI->getPointer();
5613 const int *oldc=_nodal_connec->getConstPointer();
5614 const int *ci=_nodal_connec_index->getConstPointer();
5615 for(int i=0;i<nbOfCells;i++,ci++)
5617 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5619 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5620 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5621 pt=std::copy(tmp,tmp+8,pt);
5630 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5631 ptI[1]=ptI[0]+ci[1]-ci[0];
5636 _nodal_connec->decrRef();
5637 _nodal_connec=newConn.retn();
5638 _nodal_connec_index->decrRef();
5639 _nodal_connec_index=newConnI.retn();
5646 * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5648 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5650 checkConnectivityFullyDefined();
5651 if(getMeshDimension()!=2)
5652 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5653 int nbOfCells=getNumberOfCells();
5654 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5655 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5656 ret->alloc(nbOfCells+nbOfCutCells,1);
5657 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5658 int *retPt=ret->getPointer();
5659 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5660 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5661 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5662 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5663 int *pt=newConn->getPointer();
5664 int *ptI=newConnI->getPointer();
5666 const int *oldc=_nodal_connec->getConstPointer();
5667 const int *ci=_nodal_connec_index->getConstPointer();
5668 for(int i=0;i<nbOfCells;i++,ci++)
5670 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5672 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5673 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5674 pt=std::copy(tmp,tmp+8,pt);
5683 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5684 ptI[1]=ptI[0]+ci[1]-ci[0];
5689 _nodal_connec->decrRef();
5690 _nodal_connec=newConn.retn();
5691 _nodal_connec_index->decrRef();
5692 _nodal_connec_index=newConnI.retn();
5699 * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5701 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5703 checkConnectivityFullyDefined();
5704 if(getMeshDimension()!=3)
5705 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5706 int nbOfCells=getNumberOfCells();
5707 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5708 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5709 ret->alloc(nbOfCells+4*nbOfCutCells,1);
5710 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5711 int *retPt=ret->getPointer();
5712 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5713 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5714 newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5715 newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5716 int *pt=newConn->getPointer();
5717 int *ptI=newConnI->getPointer();
5719 const int *oldc=_nodal_connec->getConstPointer();
5720 const int *ci=_nodal_connec_index->getConstPointer();
5721 for(int i=0;i<nbOfCells;i++,ci++)
5723 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5725 for(int j=0;j<5;j++,pt+=5,ptI++)
5727 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5728 pt[1]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_5_WO[4*j+0]+1]; pt[2]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_5_WO[4*j+1]+1]; pt[3]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_5_WO[4*j+2]+1]; pt[4]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_5_WO[4*j+3]+1];
5735 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5736 ptI[1]=ptI[0]+ci[1]-ci[0];
5741 _nodal_connec->decrRef();
5742 _nodal_connec=newConn.retn();
5743 _nodal_connec_index->decrRef();
5744 _nodal_connec_index=newConnI.retn();
5751 * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5753 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5755 checkConnectivityFullyDefined();
5756 if(getMeshDimension()!=3)
5757 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5758 int nbOfCells=getNumberOfCells();
5759 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5760 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5761 ret->alloc(nbOfCells+5*nbOfCutCells,1);
5762 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5763 int *retPt=ret->getPointer();
5764 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5765 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5766 newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5767 newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5768 int *pt=newConn->getPointer();
5769 int *ptI=newConnI->getPointer();
5771 const int *oldc=_nodal_connec->getConstPointer();
5772 const int *ci=_nodal_connec_index->getConstPointer();
5773 for(int i=0;i<nbOfCells;i++,ci++)
5775 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5777 for(int j=0;j<6;j++,pt+=5,ptI++)
5779 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5780 pt[1]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_6_WO[4*j+0]+1]; pt[2]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_6_WO[4*j+1]+1]; pt[3]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_6_WO[4*j+2]+1]; pt[4]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_6_WO[4*j+3]+1];
5787 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5788 ptI[1]=ptI[0]+ci[1]-ci[0];
5793 _nodal_connec->decrRef();
5794 _nodal_connec=newConn.retn();
5795 _nodal_connec_index->decrRef();
5796 _nodal_connec_index=newConnI.retn();
5803 * This private method is used to subdivide edges of a mesh with meshdim==2. If \a this has no a meshdim equal to 2 an exception will be thrown.
5804 * This method completly ignore coordinates.
5805 * \param nodeSubdived is the nodal connectivity of subdivision of edges
5806 * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5807 * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5808 * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5810 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5812 checkFullyDefined();
5813 if(getMeshDimension()!=2)
5814 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5815 int nbOfCells=getNumberOfCells();
5816 int *connI=_nodal_connec_index->getPointer();
5818 for(int i=0;i<nbOfCells;i++,connI++)
5820 int offset=descIndex[i];
5821 int nbOfEdges=descIndex[i+1]-offset;
5823 bool ddirect=desc[offset+nbOfEdges-1]>0;
5824 int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5825 int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5826 for(int j=0;j<nbOfEdges;j++)
5828 bool direct=desc[offset+j]>0;
5829 int edgeId=std::abs(desc[offset+j])-1;
5830 if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5832 int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5833 int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5834 int ref2=direct?id1:id2;
5837 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5838 newConnLgth+=nbOfSubNodes-1;
5843 std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5844 throw INTERP_KERNEL::Exception(oss.str().c_str());
5849 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5852 newConnLgth++;//+1 is for cell type
5853 connI[1]=newConnLgth;
5856 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5857 newConn->alloc(newConnLgth,1);
5858 int *work=newConn->getPointer();
5859 for(int i=0;i<nbOfCells;i++)
5861 *work++=INTERP_KERNEL::NORM_POLYGON;
5862 int offset=descIndex[i];
5863 int nbOfEdges=descIndex[i+1]-offset;
5864 for(int j=0;j<nbOfEdges;j++)
5866 bool direct=desc[offset+j]>0;
5867 int edgeId=std::abs(desc[offset+j])-1;
5869 work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5872 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5873 std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5874 work=std::copy(it,it+nbOfSubNodes-1,work);
5878 DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5881 _types.insert(INTERP_KERNEL::NORM_POLYGON);
5885 * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5886 * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5887 * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5888 * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5889 * so it can be useful to call mergeNodes() before calling this method.
5890 * \throw If \a this->getMeshDimension() <= 1.
5891 * \throw If the coordinates array is not set.
5892 * \throw If the nodal connectivity of cells is not defined.
5894 void MEDCouplingUMesh::convertDegeneratedCells()
5896 checkFullyDefined();
5897 if(getMeshDimension()<=1)
5898 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5899 int nbOfCells=getNumberOfCells();
5902 int initMeshLgth=getMeshLength();
5903 int *conn=_nodal_connec->getPointer();
5904 int *index=_nodal_connec_index->getPointer();
5908 for(int i=0;i<nbOfCells;i++)
5910 lgthOfCurCell=index[i+1]-posOfCurCell;
5911 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5913 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5914 conn+newPos+1,newLgth);
5915 conn[newPos]=newType;
5917 posOfCurCell=index[i+1];
5920 if(newPos!=initMeshLgth)
5921 _nodal_connec->reAlloc(newPos);
5926 * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5927 * A cell is considered to be oriented correctly if an angle between its
5928 * normal vector and a given vector is less than \c PI / \c 2.
5929 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5931 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5933 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5934 * is not cleared before filling in.
5935 * \throw If \a this->getMeshDimension() != 2.
5936 * \throw If \a this->getSpaceDimension() != 3.
5938 * \if ENABLE_EXAMPLES
5939 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5940 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5943 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
5945 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5946 throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5947 int nbOfCells=getNumberOfCells();
5948 const int *conn=_nodal_connec->getConstPointer();
5949 const int *connI=_nodal_connec_index->getConstPointer();
5950 const double *coordsPtr=_coords->getConstPointer();
5951 for(int i=0;i<nbOfCells;i++)
5953 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5954 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5956 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5957 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5964 * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5965 * considered to be oriented correctly if an angle between its normal vector and a
5966 * given vector is less than \c PI / \c 2.
5967 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5969 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5971 * \throw If \a this->getMeshDimension() != 2.
5972 * \throw If \a this->getSpaceDimension() != 3.
5974 * \if ENABLE_EXAMPLES
5975 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5976 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5979 * \sa changeOrientationOfCells
5981 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
5983 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5984 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5985 int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
5986 const int *connI(_nodal_connec_index->getConstPointer());
5987 const double *coordsPtr(_coords->getConstPointer());
5988 bool isModified(false);
5989 for(int i=0;i<nbOfCells;i++)
5991 INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5992 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5994 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
5995 bool isQuadratic(cm.isQuadratic());
5996 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5999 cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6004 _nodal_connec->declareAsNew();
6009 * This method change the orientation of cells in \a this without any consideration of coordinates. Only connectivity is impacted.
6011 * \sa orientCorrectly2DCells
6013 void MEDCouplingUMesh::changeOrientationOfCells()
6015 int mdim(getMeshDimension());
6016 if(mdim!=2 && mdim!=1)
6017 throw INTERP_KERNEL::Exception("Invalid mesh to apply changeOrientationOfCells on it : must be meshDim==2 or meshDim==1 !");
6018 int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6019 const int *connI(_nodal_connec_index->getConstPointer());
6022 for(int i=0;i<nbOfCells;i++)
6024 INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6025 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6026 cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6031 for(int i=0;i<nbOfCells;i++)
6033 INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6034 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6035 cm.changeOrientationOf1D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6041 * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
6042 * oriented facets. The normal vector of the facet should point out of the cell.
6043 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6044 * is not cleared before filling in.
6045 * \throw If \a this->getMeshDimension() != 3.
6046 * \throw If \a this->getSpaceDimension() != 3.
6047 * \throw If the coordinates array is not set.
6048 * \throw If the nodal connectivity of cells is not defined.
6050 * \if ENABLE_EXAMPLES
6051 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6052 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6055 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
6057 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6058 throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
6059 int nbOfCells=getNumberOfCells();
6060 const int *conn=_nodal_connec->getConstPointer();
6061 const int *connI=_nodal_connec_index->getConstPointer();
6062 const double *coordsPtr=_coords->getConstPointer();
6063 for(int i=0;i<nbOfCells;i++)
6065 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6066 if(type==INTERP_KERNEL::NORM_POLYHED)
6068 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6075 * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6077 * \throw If \a this->getMeshDimension() != 3.
6078 * \throw If \a this->getSpaceDimension() != 3.
6079 * \throw If the coordinates array is not set.
6080 * \throw If the nodal connectivity of cells is not defined.
6081 * \throw If the reparation fails.
6083 * \if ENABLE_EXAMPLES
6084 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6085 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6087 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6089 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
6091 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6092 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6093 int nbOfCells=getNumberOfCells();
6094 int *conn=_nodal_connec->getPointer();
6095 const int *connI=_nodal_connec_index->getConstPointer();
6096 const double *coordsPtr=_coords->getConstPointer();
6097 for(int i=0;i<nbOfCells;i++)
6099 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6100 if(type==INTERP_KERNEL::NORM_POLYHED)
6104 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6105 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6107 catch(INTERP_KERNEL::Exception& e)
6109 std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6110 throw INTERP_KERNEL::Exception(oss.str().c_str());
6118 * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6119 * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6120 * according to which the first facet of the cell should be oriented to have the normal vector
6121 * pointing out of cell.
6122 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6123 * cells. The caller is to delete this array using decrRef() as it is no more
6125 * \throw If \a this->getMeshDimension() != 3.
6126 * \throw If \a this->getSpaceDimension() != 3.
6127 * \throw If the coordinates array is not set.
6128 * \throw If the nodal connectivity of cells is not defined.
6130 * \if ENABLE_EXAMPLES
6131 * \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6132 * \ref py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6134 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6136 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6138 const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6139 if(getMeshDimension()!=3)
6140 throw INTERP_KERNEL::Exception(msg);
6141 int spaceDim=getSpaceDimension();
6143 throw INTERP_KERNEL::Exception(msg);
6145 int nbOfCells=getNumberOfCells();
6146 int *conn=_nodal_connec->getPointer();
6147 const int *connI=_nodal_connec_index->getConstPointer();
6148 const double *coo=getCoords()->getConstPointer();
6149 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6150 for(int i=0;i<nbOfCells;i++)
6152 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6153 if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6155 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6157 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6158 cells->pushBackSilent(i);
6162 return cells.retn();
6166 * This method is a faster method to correct orientation of all 3D cells in \a this.
6167 * This method works only if \a this is a 3D mesh, that is to say a mesh with mesh dimension 3 and a space dimension 3.
6168 * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6170 * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6171 * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons,
6173 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6175 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6176 throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6177 int nbOfCells=getNumberOfCells();
6178 int *conn=_nodal_connec->getPointer();
6179 const int *connI=_nodal_connec_index->getConstPointer();
6180 const double *coordsPtr=_coords->getConstPointer();
6181 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6182 for(int i=0;i<nbOfCells;i++)
6184 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6187 case INTERP_KERNEL::NORM_TETRA4:
6189 if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6191 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6192 ret->pushBackSilent(i);
6196 case INTERP_KERNEL::NORM_PYRA5:
6198 if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6200 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6201 ret->pushBackSilent(i);
6205 case INTERP_KERNEL::NORM_PENTA6:
6206 case INTERP_KERNEL::NORM_HEXA8:
6207 case INTERP_KERNEL::NORM_HEXGP12:
6209 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6211 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6212 ret->pushBackSilent(i);
6216 case INTERP_KERNEL::NORM_POLYHED:
6218 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6220 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6221 ret->pushBackSilent(i);
6226 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orientCorrectly3DCells : Your mesh contains type of cell not supported yet ! send mail to anthony.geay@cea.fr to add it !");
6234 * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6235 * If it is not the case an exception will be thrown.
6236 * This method is fast because the first cell of \a this is used to compute the plane.
6237 * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6238 * \param pos output of size at least 3 used to store a point owned of searched plane.
6240 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6242 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6243 throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6244 const int *conn=_nodal_connec->getConstPointer();
6245 const int *connI=_nodal_connec_index->getConstPointer();
6246 const double *coordsPtr=_coords->getConstPointer();
6247 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6248 std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6252 * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6253 * cells. Currently cells of the following types are treated:
6254 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6255 * For a cell of other type an exception is thrown.
6256 * Space dimension of a 2D mesh can be either 2 or 3.
6257 * The Edge Ratio of a cell \f$t\f$ is:
6258 * \f$\frac{|t|_\infty}{|t|_0}\f$,
6259 * where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6260 * the smallest edge lengths of \f$t\f$.
6261 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6262 * cells and one time, lying on \a this mesh. The caller is to delete this
6263 * field using decrRef() as it is no more needed.
6264 * \throw If the coordinates array is not set.
6265 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6266 * \throw If the connectivity data array has more than one component.
6267 * \throw If the connectivity data array has a named component.
6268 * \throw If the connectivity index data array has more than one component.
6269 * \throw If the connectivity index data array has a named component.
6270 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6271 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6272 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6274 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6277 int spaceDim=getSpaceDimension();
6278 int meshDim=getMeshDimension();
6279 if(spaceDim!=2 && spaceDim!=3)
6280 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6281 if(meshDim!=2 && meshDim!=3)
6282 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6283 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6285 int nbOfCells=getNumberOfCells();
6286 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6287 arr->alloc(nbOfCells,1);
6288 double *pt=arr->getPointer();
6289 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6290 const int *conn=_nodal_connec->getConstPointer();
6291 const int *connI=_nodal_connec_index->getConstPointer();
6292 const double *coo=_coords->getConstPointer();
6294 for(int i=0;i<nbOfCells;i++,pt++)
6296 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6299 case INTERP_KERNEL::NORM_TRI3:
6301 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6302 *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6305 case INTERP_KERNEL::NORM_QUAD4:
6307 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6308 *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6311 case INTERP_KERNEL::NORM_TETRA4:
6313 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6314 *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6318 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6320 conn+=connI[i+1]-connI[i];
6322 ret->setName("EdgeRatio");
6323 ret->synchronizeTimeWithSupport();
6328 * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6329 * cells. Currently cells of the following types are treated:
6330 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6331 * For a cell of other type an exception is thrown.
6332 * Space dimension of a 2D mesh can be either 2 or 3.
6333 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6334 * cells and one time, lying on \a this mesh. The caller is to delete this
6335 * field using decrRef() as it is no more needed.
6336 * \throw If the coordinates array is not set.
6337 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6338 * \throw If the connectivity data array has more than one component.
6339 * \throw If the connectivity data array has a named component.
6340 * \throw If the connectivity index data array has more than one component.
6341 * \throw If the connectivity index data array has a named component.
6342 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6343 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6344 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6346 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6349 int spaceDim=getSpaceDimension();
6350 int meshDim=getMeshDimension();
6351 if(spaceDim!=2 && spaceDim!=3)
6352 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6353 if(meshDim!=2 && meshDim!=3)
6354 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6355 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6357 int nbOfCells=getNumberOfCells();
6358 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6359 arr->alloc(nbOfCells,1);
6360 double *pt=arr->getPointer();
6361 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6362 const int *conn=_nodal_connec->getConstPointer();
6363 const int *connI=_nodal_connec_index->getConstPointer();
6364 const double *coo=_coords->getConstPointer();
6366 for(int i=0;i<nbOfCells;i++,pt++)
6368 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6371 case INTERP_KERNEL::NORM_TRI3:
6373 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6374 *pt=INTERP_KERNEL::triAspectRatio(tmp);
6377 case INTERP_KERNEL::NORM_QUAD4:
6379 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6380 *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6383 case INTERP_KERNEL::NORM_TETRA4:
6385 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6386 *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6390 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6392 conn+=connI[i+1]-connI[i];
6394 ret->setName("AspectRatio");
6395 ret->synchronizeTimeWithSupport();
6400 * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6401 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6402 * treated: INTERP_KERNEL::NORM_QUAD4.
6403 * For a cell of other type an exception is thrown.
6404 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6405 * cells and one time, lying on \a this mesh. The caller is to delete this
6406 * field using decrRef() as it is no more needed.
6407 * \throw If the coordinates array is not set.
6408 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6409 * \throw If the connectivity data array has more than one component.
6410 * \throw If the connectivity data array has a named component.
6411 * \throw If the connectivity index data array has more than one component.
6412 * \throw If the connectivity index data array has a named component.
6413 * \throw If \a this->getMeshDimension() != 2.
6414 * \throw If \a this->getSpaceDimension() != 3.
6415 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6417 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6420 int spaceDim=getSpaceDimension();
6421 int meshDim=getMeshDimension();
6423 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6425 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6426 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6428 int nbOfCells=getNumberOfCells();
6429 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6430 arr->alloc(nbOfCells,1);
6431 double *pt=arr->getPointer();
6432 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6433 const int *conn=_nodal_connec->getConstPointer();
6434 const int *connI=_nodal_connec_index->getConstPointer();
6435 const double *coo=_coords->getConstPointer();
6437 for(int i=0;i<nbOfCells;i++,pt++)
6439 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6442 case INTERP_KERNEL::NORM_QUAD4:
6444 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6445 *pt=INTERP_KERNEL::quadWarp(tmp);
6449 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6451 conn+=connI[i+1]-connI[i];
6453 ret->setName("Warp");
6454 ret->synchronizeTimeWithSupport();
6460 * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6461 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6462 * treated: INTERP_KERNEL::NORM_QUAD4.
6463 * For a cell of other type an exception is thrown.
6464 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6465 * cells and one time, lying on \a this mesh. The caller is to delete this
6466 * field using decrRef() as it is no more needed.
6467 * \throw If the coordinates array is not set.
6468 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6469 * \throw If the connectivity data array has more than one component.
6470 * \throw If the connectivity data array has a named component.
6471 * \throw If the connectivity index data array has more than one component.
6472 * \throw If the connectivity index data array has a named component.
6473 * \throw If \a this->getMeshDimension() != 2.
6474 * \throw If \a this->getSpaceDimension() != 3.
6475 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6477 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6480 int spaceDim=getSpaceDimension();
6481 int meshDim=getMeshDimension();
6483 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6485 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6486 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6488 int nbOfCells=getNumberOfCells();
6489 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6490 arr->alloc(nbOfCells,1);
6491 double *pt=arr->getPointer();
6492 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6493 const int *conn=_nodal_connec->getConstPointer();
6494 const int *connI=_nodal_connec_index->getConstPointer();
6495 const double *coo=_coords->getConstPointer();
6497 for(int i=0;i<nbOfCells;i++,pt++)
6499 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6502 case INTERP_KERNEL::NORM_QUAD4:
6504 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6505 *pt=INTERP_KERNEL::quadSkew(tmp);
6509 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6511 conn+=connI[i+1]-connI[i];
6513 ret->setName("Skew");
6514 ret->synchronizeTimeWithSupport();
6519 * Returns the cell field giving for each cell in \a this its diameter. Diameter means the max length of all possible SEG2 in the cell.
6521 * \return a new instance of field containing the result. The returned instance has to be deallocated by the caller.
6523 * \sa getSkewField, getWarpField, getAspectRatioField, getEdgeRatioField
6525 MEDCouplingFieldDouble *MEDCouplingUMesh::computeDiameterField() const
6528 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME));
6530 std::set<INTERP_KERNEL::NormalizedCellType> types;
6531 ComputeAllTypesInternal(types,_nodal_connec,_nodal_connec_index);
6532 int spaceDim(getSpaceDimension()),nbCells(getNumberOfCells());
6533 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::New());
6534 arr->alloc(nbCells,1);
6535 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++)
6537 INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::DiameterCalculator> dc(INTERP_KERNEL::CellModel::GetCellModel(*it).buildInstanceOfDiameterCalulator(spaceDim));
6538 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds(giveCellsWithType(*it));
6539 dc->computeForListOfCellIdsUMeshFrmt(cellIds->begin(),cellIds->end(),_nodal_connec_index->begin(),_nodal_connec->begin(),getCoords()->begin(),arr->getPointer());
6542 ret->setName("Diameter");
6547 * This method aggregate the bbox of each cell and put it into bbox parameter.
6549 * \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)
6550 * For all other cases this input parameter is ignored.
6551 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6553 * \throw If \a this is not fully set (coordinates and connectivity).
6554 * \throw If a cell in \a this has no valid nodeId.
6555 * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6557 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6559 int mDim(getMeshDimension()),sDim(getSpaceDimension());
6560 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.
6561 return getBoundingBoxForBBTreeFast();
6562 if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6564 bool presenceOfQuadratic(false);
6565 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6567 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6568 if(cm.isQuadratic())
6569 presenceOfQuadratic=true;
6571 if(!presenceOfQuadratic)
6572 return getBoundingBoxForBBTreeFast();
6573 if(mDim==2 && sDim==2)
6574 return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6576 return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6578 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) !");
6582 * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6583 * So meshes having quadratic cells the computed bounding boxes can be invalid !
6585 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6587 * \throw If \a this is not fully set (coordinates and connectivity).
6588 * \throw If a cell in \a this has no valid nodeId.
6590 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6592 checkFullyDefined();
6593 int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6594 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6595 double *bbox(ret->getPointer());
6596 for(int i=0;i<nbOfCells*spaceDim;i++)
6598 bbox[2*i]=std::numeric_limits<double>::max();
6599 bbox[2*i+1]=-std::numeric_limits<double>::max();
6601 const double *coordsPtr(_coords->getConstPointer());
6602 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6603 for(int i=0;i<nbOfCells;i++)
6605 int offset=connI[i]+1;
6606 int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6607 for(int j=0;j<nbOfNodesForCell;j++)
6609 int nodeId=conn[offset+j];
6610 if(nodeId>=0 && nodeId<nbOfNodes)
6612 for(int k=0;k<spaceDim;k++)
6614 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6615 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6622 std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6623 throw INTERP_KERNEL::Exception(oss.str().c_str());
6630 * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6631 * useful for 2D meshes having quadratic cells
6632 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6633 * the two extremities of the arc of circle).
6635 * \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)
6636 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6637 * \throw If \a this is not fully defined.
6638 * \throw If \a this is not a mesh with meshDimension equal to 2.
6639 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6640 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6642 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6644 checkFullyDefined();
6645 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6646 if(spaceDim!=2 || mDim!=2)
6647 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!");
6648 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6649 double *bbox(ret->getPointer());
6650 const double *coords(_coords->getConstPointer());
6651 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6652 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6654 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6655 int sz(connI[1]-connI[0]-1);
6656 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6657 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6658 INTERP_KERNEL::QuadraticPolygon *pol(0);
6659 for(int j=0;j<sz;j++)
6661 int nodeId(conn[*connI+1+j]);
6662 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6664 if(!cm.isQuadratic())
6665 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6667 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6668 INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6669 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax();
6675 * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6676 * useful for 2D meshes having quadratic cells
6677 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6678 * the two extremities of the arc of circle).
6680 * \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)
6681 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6682 * \throw If \a this is not fully defined.
6683 * \throw If \a this is not a mesh with meshDimension equal to 1.
6684 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6685 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6687 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6689 checkFullyDefined();
6690 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6691 if(spaceDim!=2 || mDim!=1)
6692 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!");
6693 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6694 double *bbox(ret->getPointer());
6695 const double *coords(_coords->getConstPointer());
6696 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6697 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6699 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6700 int sz(connI[1]-connI[0]-1);
6701 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6702 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6703 INTERP_KERNEL::Edge *edge(0);
6704 for(int j=0;j<sz;j++)
6706 int nodeId(conn[*connI+1+j]);
6707 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6709 if(!cm.isQuadratic())
6710 edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6712 edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6713 const INTERP_KERNEL::Bounds& b(edge->getBounds());
6714 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6721 namespace ParaMEDMEMImpl
6726 ConnReader(const int *c, int val):_conn(c),_val(val) { }
6727 bool operator() (const int& pos) { return _conn[pos]!=_val; }
6736 ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6737 bool operator() (const int& pos) { return _conn[pos]==_val; }
6747 * This method expects that \a this is sorted by types. If not an exception will be thrown.
6748 * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6749 * \a this is composed in cell types.
6750 * The returned array is of size 3*n where n is the number of different types present in \a this.
6751 * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here.
6752 * This parameter is kept only for compatibility with other methode listed above.
6754 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6756 checkConnectivityFullyDefined();
6757 const int *conn=_nodal_connec->getConstPointer();
6758 const int *connI=_nodal_connec_index->getConstPointer();
6759 const int *work=connI;
6760 int nbOfCells=getNumberOfCells();
6761 std::size_t n=getAllGeoTypes().size();
6762 std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6763 std::set<INTERP_KERNEL::NormalizedCellType> types;
6764 for(std::size_t i=0;work!=connI+nbOfCells;i++)
6766 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6767 if(types.find(typ)!=types.end())
6769 std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6770 oss << " is not contiguous !";
6771 throw INTERP_KERNEL::Exception(oss.str().c_str());
6775 const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6776 ret[3*i+1]=(int)std::distance(work,work2);
6783 * This method is used to check that this has contiguous cell type in same order than described in \a code.
6784 * only for types cell, type node is not managed.
6785 * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6786 * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6787 * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6788 * If 2 or more same geometric type is in \a code and exception is thrown too.
6790 * This method firstly checks
6791 * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6792 * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6793 * an exception is thrown too.
6795 * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6796 * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown
6797 * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6799 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6802 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6803 std::size_t sz=code.size();
6806 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6807 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6809 bool isNoPflUsed=true;
6810 for(std::size_t i=0;i<n;i++)
6811 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6813 types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6815 if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6816 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6817 isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6820 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6823 if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6824 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6825 if(types.size()==_types.size())
6828 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6830 int *retPtr=ret->getPointer();
6831 const int *connI=_nodal_connec_index->getConstPointer();
6832 const int *conn=_nodal_connec->getConstPointer();
6833 int nbOfCells=getNumberOfCells();
6836 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6838 i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6839 int offset=(int)std::distance(connI,i);
6840 const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6841 int nbOfCellsOfCurType=(int)std::distance(i,j);
6842 if(code[3*kk+2]==-1)
6843 for(int k=0;k<nbOfCellsOfCurType;k++)
6847 int idInIdsPerType=code[3*kk+2];
6848 if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6850 const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6853 zePfl->checkAllocated();
6854 if(zePfl->getNumberOfComponents()==1)
6856 for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6858 if(*k>=0 && *k<nbOfCellsOfCurType)
6859 *retPtr=(*k)+offset;
6862 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6863 oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6864 throw INTERP_KERNEL::Exception(oss.str().c_str());
6869 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6872 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6876 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6877 oss << " should be in [0," << idsPerType.size() << ") !";
6878 throw INTERP_KERNEL::Exception(oss.str().c_str());
6887 * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6888 * 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.
6889 * 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.
6890 * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6892 * \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.
6893 * \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,
6894 * \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6895 * \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.
6896 * This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6897 * \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
6899 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6902 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6903 if(profile->getNumberOfComponents()!=1)
6904 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6905 checkConnectivityFullyDefined();
6906 const int *conn=_nodal_connec->getConstPointer();
6907 const int *connI=_nodal_connec_index->getConstPointer();
6908 int nbOfCells=getNumberOfCells();
6909 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6910 std::vector<int> typeRangeVals(1);
6911 for(const int *i=connI;i!=connI+nbOfCells;)
6913 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6914 if(std::find(types.begin(),types.end(),curType)!=types.end())
6916 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6918 types.push_back(curType);
6919 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6920 typeRangeVals.push_back((int)std::distance(connI,i));
6923 DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6924 profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6925 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6926 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6927 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6929 int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6930 code.resize(3*nbOfCastsFinal);
6931 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6932 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6933 for(int i=0;i<nbOfCastsFinal;i++)
6935 int castId=castsPresent->getIJ(i,0);
6936 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6937 idsInPflPerType2.push_back(tmp3);
6938 code[3*i]=(int)types[castId];
6939 code[3*i+1]=tmp3->getNumberOfTuples();
6940 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6941 if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6943 tmp4->copyStringInfoFrom(*profile);
6944 idsPerType2.push_back(tmp4);
6945 code[3*i+2]=(int)idsPerType2.size()-1;
6952 std::size_t sz2=idsInPflPerType2.size();
6953 idsInPflPerType.resize(sz2);
6954 for(std::size_t i=0;i<sz2;i++)
6956 DataArrayInt *locDa=idsInPflPerType2[i];
6958 idsInPflPerType[i]=locDa;
6960 std::size_t sz=idsPerType2.size();
6961 idsPerType.resize(sz);
6962 for(std::size_t i=0;i<sz;i++)
6964 DataArrayInt *locDa=idsPerType2[i];
6966 idsPerType[i]=locDa;
6971 * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6972 * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6973 * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6974 * 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.
6976 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
6978 checkFullyDefined();
6979 nM1LevMesh->checkFullyDefined();
6980 if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6981 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6982 if(_coords!=nM1LevMesh->getCoords())
6983 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6984 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6985 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6986 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6987 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6988 desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6989 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6990 tmp->setConnectivity(tmp0,tmp1);
6991 tmp->renumberCells(ret0->getConstPointer(),false);
6992 revDesc=tmp->getNodalConnectivity();
6993 revDescIndx=tmp->getNodalConnectivityIndex();
6994 DataArrayInt *ret=0;
6995 if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6998 ret->getMaxValue(tmp2);
7000 std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
7001 throw INTERP_KERNEL::Exception(oss.str().c_str());
7006 revDescIndx->incrRef();
7009 meshnM1Old2New=ret0;
7014 * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
7015 * necessary for writing the mesh to MED file. Additionally returns a permutation array
7016 * in "Old to New" mode.
7017 * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
7018 * this array using decrRef() as it is no more needed.
7019 * \throw If the nodal connectivity of cells is not defined.
7021 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
7023 checkConnectivityFullyDefined();
7024 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
7025 renumberCells(ret->getConstPointer(),false);
7030 * This methods checks that cells are sorted by their types.
7031 * This method makes asumption (no check) that connectivity is correctly set before calling.
7033 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
7035 checkFullyDefined();
7036 const int *conn=_nodal_connec->getConstPointer();
7037 const int *connI=_nodal_connec_index->getConstPointer();
7038 int nbOfCells=getNumberOfCells();
7039 std::set<INTERP_KERNEL::NormalizedCellType> types;
7040 for(const int *i=connI;i!=connI+nbOfCells;)
7042 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7043 if(types.find(curType)!=types.end())
7045 types.insert(curType);
7046 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7052 * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
7053 * The geometric type order is specified by MED file.
7055 * \sa MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
7057 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
7059 return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7063 * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
7064 * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
7065 * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
7066 * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
7068 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7070 checkFullyDefined();
7071 const int *conn=_nodal_connec->getConstPointer();
7072 const int *connI=_nodal_connec_index->getConstPointer();
7073 int nbOfCells=getNumberOfCells();
7077 std::set<INTERP_KERNEL::NormalizedCellType> sg;
7078 for(const int *i=connI;i!=connI+nbOfCells;)
7080 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7081 const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
7082 if(isTypeExists!=orderEnd)
7084 int pos=(int)std::distance(orderBg,isTypeExists);
7088 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7092 if(sg.find(curType)==sg.end())
7094 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7105 * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
7106 * 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
7107 * 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'.
7109 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
7111 checkConnectivityFullyDefined();
7112 int nbOfCells=getNumberOfCells();
7113 const int *conn=_nodal_connec->getConstPointer();
7114 const int *connI=_nodal_connec_index->getConstPointer();
7115 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
7116 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
7117 tmpa->alloc(nbOfCells,1);
7118 tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
7119 tmpb->fillWithZero();
7120 int *tmp=tmpa->getPointer();
7121 int *tmp2=tmpb->getPointer();
7122 for(const int *i=connI;i!=connI+nbOfCells;i++)
7124 const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
7127 int pos=(int)std::distance(orderBg,where);
7129 tmp[std::distance(connI,i)]=pos;
7133 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
7134 std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
7135 oss << " has a type " << cm.getRepr() << " not in input array of type !";
7136 throw INTERP_KERNEL::Exception(oss.str().c_str());
7139 nbPerType=tmpb.retn();
7144 * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7146 * \return a new object containing the old to new correspondance.
7148 * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7150 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7152 return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7156 * 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.
7157 * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7158 * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7159 * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7161 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7163 DataArrayInt *nbPerType=0;
7164 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7165 nbPerType->decrRef();
7166 return tmpa->buildPermArrPerLevel();
7170 * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7171 * The number of cells remains unchanged after the call of this method.
7172 * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7173 * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7175 * \return the array giving the correspondance old to new.
7177 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7179 checkFullyDefined();
7181 const int *conn=_nodal_connec->getConstPointer();
7182 const int *connI=_nodal_connec_index->getConstPointer();
7183 int nbOfCells=getNumberOfCells();
7184 std::vector<INTERP_KERNEL::NormalizedCellType> types;
7185 for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7186 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7188 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7189 types.push_back(curType);
7190 for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7192 DataArrayInt *ret=DataArrayInt::New();
7193 ret->alloc(nbOfCells,1);
7194 int *retPtr=ret->getPointer();
7195 std::fill(retPtr,retPtr+nbOfCells,-1);
7197 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7199 for(const int *i=connI;i!=connI+nbOfCells;i++)
7200 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7201 retPtr[std::distance(connI,i)]=newCellId++;
7203 renumberCells(retPtr,false);
7208 * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7209 * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7210 * This method makes asumption that connectivity is correctly set before calling.
7212 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7214 checkConnectivityFullyDefined();
7215 const int *conn=_nodal_connec->getConstPointer();
7216 const int *connI=_nodal_connec_index->getConstPointer();
7217 int nbOfCells=getNumberOfCells();
7218 std::vector<MEDCouplingUMesh *> ret;
7219 for(const int *i=connI;i!=connI+nbOfCells;)
7221 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7222 int beginCellId=(int)std::distance(connI,i);
7223 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7224 int endCellId=(int)std::distance(connI,i);
7225 int sz=endCellId-beginCellId;
7226 int *cells=new int[sz];
7227 for(int j=0;j<sz;j++)
7228 cells[j]=beginCellId+j;
7229 MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7237 * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7238 * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7239 * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7241 * \return a newly allocated instance, that the caller must manage.
7242 * \throw If \a this contains more than one geometric type.
7243 * \throw If the nodal connectivity of \a this is not fully defined.
7244 * \throw If the internal data is not coherent.
7246 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7248 checkConnectivityFullyDefined();
7249 if(_types.size()!=1)
7250 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7251 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7252 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7253 ret->setCoords(getCoords());
7254 MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7257 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7258 retC->setNodalConnectivity(c);
7262 MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7264 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7265 DataArrayInt *c=0,*ci=0;
7266 convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7267 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7268 retD->setNodalConnectivity(cs,cis);
7273 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7275 checkConnectivityFullyDefined();
7276 if(_types.size()!=1)
7277 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7278 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7279 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7282 std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7283 oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7284 throw INTERP_KERNEL::Exception(oss.str().c_str());
7286 int nbCells=getNumberOfCells();
7288 int nbNodesPerCell=(int)cm.getNumberOfNodes();
7289 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7290 int *outPtr=connOut->getPointer();
7291 const int *conn=_nodal_connec->begin();
7292 const int *connI=_nodal_connec_index->begin();
7294 for(int i=0;i<nbCells;i++,connI++)
7296 if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7297 outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7300 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 << ") !";
7301 throw INTERP_KERNEL::Exception(oss.str().c_str());
7304 return connOut.retn();
7307 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7309 static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7310 checkConnectivityFullyDefined();
7311 if(_types.size()!=1)
7312 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7313 int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7315 throw INTERP_KERNEL::Exception(msg0);
7316 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7317 c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7318 int *cp(c->getPointer()),*cip(ci->getPointer());
7319 const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7321 for(int i=0;i<nbCells;i++,cip++,incip++)
7323 int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7324 int delta(stop-strt);
7327 if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7328 cp=std::copy(incp+strt,incp+stop,cp);
7330 throw INTERP_KERNEL::Exception(msg0);
7333 throw INTERP_KERNEL::Exception(msg0);
7334 cip[1]=cip[0]+delta;
7336 nodalConn=c.retn(); nodalConnIndex=ci.retn();
7340 * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7341 * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7342 * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7343 * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7344 * are not used here to avoid the build of big permutation array.
7346 * \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
7347 * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7348 * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7349 * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7350 * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7351 * output array gives for each chunck of same type the corresponding mesh id in \b ms.
7352 * \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
7353 * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7355 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7356 DataArrayInt *&szOfCellGrpOfSameType,
7357 DataArrayInt *&idInMsOfCellGrpOfSameType)
7359 std::vector<const MEDCouplingUMesh *> ms2;
7360 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7363 (*it)->checkConnectivityFullyDefined();
7367 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7368 const DataArrayDouble *refCoo=ms2[0]->getCoords();
7369 int meshDim=ms2[0]->getMeshDimension();
7370 std::vector<const MEDCouplingUMesh *> m1ssm;
7371 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7373 std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7374 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7376 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7377 ret1->alloc(0,1); ret2->alloc(0,1);
7378 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7380 if(meshDim!=(*it)->getMeshDimension())
7381 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7382 if(refCoo!=(*it)->getCoords())
7383 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7384 std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7385 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7386 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7387 for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7389 MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7390 m1ssmSingleAuto.push_back(singleCell);
7391 m1ssmSingle.push_back(singleCell);
7392 ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7395 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7396 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7397 std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7398 for(std::size_t i=0;i<m1ssm.size();i++)
7399 m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7400 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7401 szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7402 idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7407 * This method returns a newly created DataArrayInt instance.
7408 * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7410 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7412 checkFullyDefined();
7413 const int *conn=_nodal_connec->getConstPointer();
7414 const int *connIndex=_nodal_connec_index->getConstPointer();
7415 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7416 for(const int *w=begin;w!=end;w++)
7417 if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7418 ret->pushBackSilent(*w);
7423 * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7424 * are in [0:getNumberOfCells())
7426 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7428 checkFullyDefined();
7429 const int *conn=_nodal_connec->getConstPointer();
7430 const int *connI=_nodal_connec_index->getConstPointer();
7431 int nbOfCells=getNumberOfCells();
7432 std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7433 int *tmp=new int[nbOfCells];
7434 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7437 for(const int *i=connI;i!=connI+nbOfCells;i++)
7438 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7439 tmp[std::distance(connI,i)]=j++;
7441 DataArrayInt *ret=DataArrayInt::New();
7442 ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7443 ret->copyStringInfoFrom(*da);
7444 int *retPtr=ret->getPointer();
7445 const int *daPtr=da->getConstPointer();
7446 int nbOfElems=da->getNbOfElems();
7447 for(int k=0;k<nbOfElems;k++)
7448 retPtr[k]=tmp[daPtr[k]];
7454 * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7455 * This method \b works \b for mesh sorted by type.
7456 * cells whose ids is in 'idsPerGeoType' array.
7457 * This method conserves coords and name of mesh.
7459 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7461 std::vector<int> code=getDistributionOfTypes();
7462 std::size_t nOfTypesInThis=code.size()/3;
7463 int sz=0,szOfType=0;
7464 for(std::size_t i=0;i<nOfTypesInThis;i++)
7469 szOfType=code[3*i+1];
7471 for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7472 if(*work<0 || *work>=szOfType)
7474 std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7475 oss << ". It should be in [0," << szOfType << ") !";
7476 throw INTERP_KERNEL::Exception(oss.str().c_str());
7478 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7479 int *idsPtr=idsTokeep->getPointer();
7481 for(std::size_t i=0;i<nOfTypesInThis;i++)
7484 for(int j=0;j<code[3*i+1];j++)
7487 idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7488 offset+=code[3*i+1];
7490 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7491 ret->copyTinyInfoFrom(this);
7496 * This method returns a vector of size 'this->getNumberOfCells()'.
7497 * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7499 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7501 int ncell=getNumberOfCells();
7502 std::vector<bool> ret(ncell);
7503 const int *cI=getNodalConnectivityIndex()->getConstPointer();
7504 const int *c=getNodalConnectivity()->getConstPointer();
7505 for(int i=0;i<ncell;i++)
7507 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7508 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7509 ret[i]=cm.isQuadratic();
7515 * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7517 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7519 if(other->getType()!=UNSTRUCTURED)
7520 throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7521 const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7522 return MergeUMeshes(this,otherC);
7526 * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7527 * computed by averaging coordinates of cell nodes, so this method is not a right
7528 * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7529 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7530 * this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7531 * components. The caller is to delete this array using decrRef() as it is
7533 * \throw If the coordinates array is not set.
7534 * \throw If the nodal connectivity of cells is not defined.
7535 * \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7537 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7539 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7540 int spaceDim=getSpaceDimension();
7541 int nbOfCells=getNumberOfCells();
7542 ret->alloc(nbOfCells,spaceDim);
7543 ret->copyStringInfoFrom(*getCoords());
7544 double *ptToFill=ret->getPointer();
7545 const int *nodal=_nodal_connec->getConstPointer();
7546 const int *nodalI=_nodal_connec_index->getConstPointer();
7547 const double *coor=_coords->getConstPointer();
7548 for(int i=0;i<nbOfCells;i++)
7550 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7551 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7558 * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7559 * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the
7561 * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned
7562 * DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7564 * \sa MEDCouplingUMesh::getBarycenterAndOwner
7565 * \throw If \a this is not fully defined (coordinates and connectivity)
7566 * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7568 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7570 checkFullyDefined();
7571 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7572 int spaceDim=getSpaceDimension();
7573 int nbOfCells=getNumberOfCells();
7574 int nbOfNodes=getNumberOfNodes();
7575 ret->alloc(nbOfCells,spaceDim);
7576 double *ptToFill=ret->getPointer();
7577 const int *nodal=_nodal_connec->getConstPointer();
7578 const int *nodalI=_nodal_connec_index->getConstPointer();
7579 const double *coor=_coords->getConstPointer();
7580 for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7582 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7583 std::fill(ptToFill,ptToFill+spaceDim,0.);
7584 if(type!=INTERP_KERNEL::NORM_POLYHED)
7586 for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7588 if(*conn>=0 && *conn<nbOfNodes)
7589 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7592 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," << nbOfNodes << ") !";
7593 throw INTERP_KERNEL::Exception(oss.str().c_str());
7596 int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7597 if(nbOfNodesInCell>0)
7598 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7601 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7602 throw INTERP_KERNEL::Exception(oss.str().c_str());
7607 std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7609 for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7611 if(*it>=0 && *it<nbOfNodes)
7612 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7615 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," << nbOfNodes << ") !";
7616 throw INTERP_KERNEL::Exception(oss.str().c_str());
7620 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7623 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7624 throw INTERP_KERNEL::Exception(oss.str().c_str());
7632 * Returns a new DataArrayDouble holding barycenters of specified cells. The
7633 * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7634 * are specified via an array of cell ids.
7635 * \warning Validity of the specified cell ids is not checked!
7636 * Valid range is [ 0, \a this->getNumberOfCells() ).
7637 * \param [in] begin - an array of cell ids of interest.
7638 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7639 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7640 * end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7641 * caller is to delete this array using decrRef() as it is no more needed.
7642 * \throw If the coordinates array is not set.
7643 * \throw If the nodal connectivity of cells is not defined.
7645 * \if ENABLE_EXAMPLES
7646 * \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7647 * \ref py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7650 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7652 DataArrayDouble *ret=DataArrayDouble::New();
7653 int spaceDim=getSpaceDimension();
7654 int nbOfTuple=(int)std::distance(begin,end);
7655 ret->alloc(nbOfTuple,spaceDim);
7656 double *ptToFill=ret->getPointer();
7657 double *tmp=new double[spaceDim];
7658 const int *nodal=_nodal_connec->getConstPointer();
7659 const int *nodalI=_nodal_connec_index->getConstPointer();
7660 const double *coor=_coords->getConstPointer();
7661 for(const int *w=begin;w!=end;w++)
7663 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7664 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7672 * 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".
7673 * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7674 * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7675 * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7676 * This method is useful to detect 2D cells in 3D space that are not coplanar.
7678 * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7679 * \throw If spaceDim!=3 or meshDim!=2.
7680 * \throw If connectivity of \a this is invalid.
7681 * \throw If connectivity of a cell in \a this points to an invalid node.
7683 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7685 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7686 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7687 if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7688 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7689 ret->alloc(nbOfCells,4);
7690 double *retPtr(ret->getPointer());
7691 const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7692 const double *coor(_coords->begin());
7693 for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7695 double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7696 if(nodalI[1]-nodalI[0]>=3)
7698 for(int j=0;j<3;j++)
7700 int nodeId(nodal[nodalI[0]+1+j]);
7701 if(nodeId>=0 && nodeId<nbOfNodes)
7702 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7705 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7706 throw INTERP_KERNEL::Exception(oss.str().c_str());
7712 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7713 throw INTERP_KERNEL::Exception(oss.str().c_str());
7715 INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7716 retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7722 * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7725 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7728 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7729 da->checkAllocated();
7730 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7732 int nbOfTuples=da->getNumberOfTuples();
7733 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7734 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7735 c->alloc(2*nbOfTuples,1);
7736 cI->alloc(nbOfTuples+1,1);
7737 int *cp=c->getPointer();
7738 int *cip=cI->getPointer();
7740 for(int i=0;i<nbOfTuples;i++)
7742 *cp++=INTERP_KERNEL::NORM_POINT1;
7746 ret->setConnectivity(c,cI,true);
7750 * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7751 * Cells and nodes of
7752 * the first mesh precede cells and nodes of the second mesh within the result mesh.
7753 * \param [in] mesh1 - the first mesh.
7754 * \param [in] mesh2 - the second mesh.
7755 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7756 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7757 * is no more needed.
7758 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7759 * \throw If the coordinates array is not set in none of the meshes.
7760 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7761 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7763 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7765 std::vector<const MEDCouplingUMesh *> tmp(2);
7766 tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7767 return MergeUMeshes(tmp);
7771 * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7772 * Cells and nodes of
7773 * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7774 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7775 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7776 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7777 * is no more needed.
7778 * \throw If \a a.size() == 0.
7779 * \throw If \a a[ *i* ] == NULL.
7780 * \throw If the coordinates array is not set in none of the meshes.
7781 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7782 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7784 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7786 std::size_t sz=a.size();
7788 return MergeUMeshesLL(a);
7789 for(std::size_t ii=0;ii<sz;ii++)
7792 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7793 throw INTERP_KERNEL::Exception(oss.str().c_str());
7795 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7796 std::vector< const MEDCouplingUMesh * > aa(sz);
7798 for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7800 const MEDCouplingUMesh *cur=a[i];
7801 const DataArrayDouble *coo=cur->getCoords();
7803 spaceDim=coo->getNumberOfComponents();
7806 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7807 for(std::size_t i=0;i<sz;i++)
7809 bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7812 return MergeUMeshesLL(aa);
7817 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7820 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7821 std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7822 int meshDim=(*it)->getMeshDimension();
7823 int nbOfCells=(*it)->getNumberOfCells();
7824 int meshLgth=(*it++)->getMeshLength();
7825 for(;it!=a.end();it++)
7827 if(meshDim!=(*it)->getMeshDimension())
7828 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7829 nbOfCells+=(*it)->getNumberOfCells();
7830 meshLgth+=(*it)->getMeshLength();
7832 std::vector<const MEDCouplingPointSet *> aps(a.size());
7833 std::copy(a.begin(),a.end(),aps.begin());
7834 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7835 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7836 ret->setCoords(pts);
7837 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7838 c->alloc(meshLgth,1);
7839 int *cPtr=c->getPointer();
7840 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7841 cI->alloc(nbOfCells+1,1);
7842 int *cIPtr=cI->getPointer();
7846 for(it=a.begin();it!=a.end();it++)
7848 int curNbOfCell=(*it)->getNumberOfCells();
7849 const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7850 const int *curC=(*it)->_nodal_connec->getConstPointer();
7851 cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7852 for(int j=0;j<curNbOfCell;j++)
7854 const int *src=curC+curCI[j];
7856 for(;src!=curC+curCI[j+1];src++,cPtr++)
7864 offset+=curCI[curNbOfCell];
7865 offset2+=(*it)->getNumberOfNodes();
7868 ret->setConnectivity(c,cI,true);
7875 * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7876 * dimension and sharing the node coordinates array.
7877 * All cells of the first mesh precede all cells of the second mesh
7878 * within the result mesh.
7879 * \param [in] mesh1 - the first mesh.
7880 * \param [in] mesh2 - the second mesh.
7881 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7882 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7883 * is no more needed.
7884 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7885 * \throw If the meshes do not share the node coordinates array.
7886 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7887 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7889 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7891 std::vector<const MEDCouplingUMesh *> tmp(2);
7892 tmp[0]=mesh1; tmp[1]=mesh2;
7893 return MergeUMeshesOnSameCoords(tmp);
7897 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7898 * dimension and sharing the node coordinates array.
7899 * All cells of the *i*-th mesh precede all cells of the
7900 * (*i*+1)-th mesh within the result mesh.
7901 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7902 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7903 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7904 * is no more needed.
7905 * \throw If \a a.size() == 0.
7906 * \throw If \a a[ *i* ] == NULL.
7907 * \throw If the meshes do not share the node coordinates array.
7908 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7909 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7911 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7914 throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7915 for(std::size_t ii=0;ii<meshes.size();ii++)
7918 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7919 throw INTERP_KERNEL::Exception(oss.str().c_str());
7921 const DataArrayDouble *coords=meshes.front()->getCoords();
7922 int meshDim=meshes.front()->getMeshDimension();
7923 std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7925 int meshIndexLgth=0;
7926 for(;iter!=meshes.end();iter++)
7928 if(coords!=(*iter)->getCoords())
7929 throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7930 if(meshDim!=(*iter)->getMeshDimension())
7931 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7932 meshLgth+=(*iter)->getMeshLength();
7933 meshIndexLgth+=(*iter)->getNumberOfCells();
7935 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7936 nodal->alloc(meshLgth,1);
7937 int *nodalPtr=nodal->getPointer();
7938 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7939 nodalIndex->alloc(meshIndexLgth+1,1);
7940 int *nodalIndexPtr=nodalIndex->getPointer();
7942 for(iter=meshes.begin();iter!=meshes.end();iter++)
7944 const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7945 const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7946 int nbOfCells=(*iter)->getNumberOfCells();
7947 int meshLgth2=(*iter)->getMeshLength();
7948 nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7949 if(iter!=meshes.begin())
7950 nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7952 nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7955 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7956 ret->setName("merge");
7957 ret->setMeshDimension(meshDim);
7958 ret->setConnectivity(nodal,nodalIndex,true);
7959 ret->setCoords(coords);
7964 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7965 * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7966 * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7967 * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7968 * New" mode are returned for each input mesh.
7969 * \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7970 * \param [in] compType - specifies a cell comparison technique. For meaning of its
7971 * valid values [0,1,2], see zipConnectivityTraducer().
7972 * \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7973 * meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7974 * mesh. The caller is to delete each of the arrays using decrRef() as it is
7976 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7977 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7978 * is no more needed.
7979 * \throw If \a meshes.size() == 0.
7980 * \throw If \a meshes[ *i* ] == NULL.
7981 * \throw If the meshes do not share the node coordinates array.
7982 * \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7983 * \throw If the \a meshes are of different dimension (getMeshDimension()).
7984 * \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7985 * \throw If the nodal connectivity any of \a meshes includes an invalid id.
7987 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7989 //All checks are delegated to MergeUMeshesOnSameCoords
7990 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7991 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7992 corr.resize(meshes.size());
7993 std::size_t nbOfMeshes=meshes.size();
7995 const int *o2nPtr=o2n->getConstPointer();
7996 for(std::size_t i=0;i<nbOfMeshes;i++)
7998 DataArrayInt *tmp=DataArrayInt::New();
7999 int curNbOfCells=meshes[i]->getNumberOfCells();
8000 tmp->alloc(curNbOfCells,1);
8001 std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
8002 offset+=curNbOfCells;
8003 tmp->setName(meshes[i]->getName());
8010 * Makes all given meshes share the nodal connectivity array. The common connectivity
8011 * array is created by concatenating the connectivity arrays of all given meshes. All
8012 * the given meshes must be of the same space dimension but dimension of cells **can
8013 * differ**. This method is particulary useful in MEDLoader context to build a \ref
8014 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8015 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8016 * \param [in,out] meshes - a vector of meshes to update.
8017 * \throw If any of \a meshes is NULL.
8018 * \throw If the coordinates array is not set in any of \a meshes.
8019 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8020 * \throw If \a meshes are of different space dimension.
8022 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
8024 std::size_t sz=meshes.size();
8027 std::vector< const DataArrayDouble * > coords(meshes.size());
8028 std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
8029 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
8033 (*it)->checkConnectivityFullyDefined();
8034 const DataArrayDouble *coo=(*it)->getCoords();
8039 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8040 oss << " has no coordinate array defined !";
8041 throw INTERP_KERNEL::Exception(oss.str().c_str());
8046 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8047 oss << " is null !";
8048 throw INTERP_KERNEL::Exception(oss.str().c_str());
8051 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
8052 std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
8053 int offset=(*it)->getNumberOfNodes();
8054 (*it++)->setCoords(res);
8055 for(;it!=meshes.end();it++)
8057 int oldNumberOfNodes=(*it)->getNumberOfNodes();
8058 (*it)->setCoords(res);
8059 (*it)->shiftNodeNumbersInConn(offset);
8060 offset+=oldNumberOfNodes;
8065 * Merges nodes coincident with a given precision within all given meshes that share
8066 * the nodal connectivity array. The given meshes **can be of different** mesh
8067 * dimension. This method is particulary useful in MEDLoader context to build a \ref
8068 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8069 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8070 * \param [in,out] meshes - a vector of meshes to update.
8071 * \param [in] eps - the precision used to detect coincident nodes (infinite norm).
8072 * \throw If any of \a meshes is NULL.
8073 * \throw If the \a meshes do not share the same node coordinates array.
8074 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8076 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
8080 std::set<const DataArrayDouble *> s;
8081 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8084 s.insert((*it)->getCoords());
8087 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 !";
8088 throw INTERP_KERNEL::Exception(oss.str().c_str());
8093 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 !";
8094 throw INTERP_KERNEL::Exception(oss.str().c_str());
8096 const DataArrayDouble *coo=*(s.begin());
8100 DataArrayInt *comm,*commI;
8101 coo->findCommonTuples(eps,-1,comm,commI);
8102 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
8103 int oldNbOfNodes=coo->getNumberOfTuples();
8105 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
8106 if(oldNbOfNodes==newNbOfNodes)
8108 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
8109 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8111 (*it)->renumberNodesInConn(o2n->getConstPointer());
8112 (*it)->setCoords(newCoords);
8117 * 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.
8118 * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
8119 * \param isQuad specifies the policy of connectivity.
8120 * @ret in/out parameter in which the result will be append
8122 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
8124 INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
8125 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
8126 ret.push_back(cm.getExtrudedType());
8127 int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
8130 case INTERP_KERNEL::NORM_POINT1:
8132 ret.push_back(connBg[1]);
8133 ret.push_back(connBg[1]+nbOfNodesPerLev);
8136 case INTERP_KERNEL::NORM_SEG2:
8138 int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
8139 ret.insert(ret.end(),conn,conn+4);
8142 case INTERP_KERNEL::NORM_SEG3:
8144 int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8145 ret.insert(ret.end(),conn,conn+8);
8148 case INTERP_KERNEL::NORM_QUAD4:
8150 int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8151 ret.insert(ret.end(),conn,conn+8);
8154 case INTERP_KERNEL::NORM_TRI3:
8156 int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8157 ret.insert(ret.end(),conn,conn+6);
8160 case INTERP_KERNEL::NORM_TRI6:
8162 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,
8163 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8164 ret.insert(ret.end(),conn,conn+15);
8167 case INTERP_KERNEL::NORM_QUAD8:
8170 connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8171 connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8172 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8174 ret.insert(ret.end(),conn,conn+20);
8177 case INTERP_KERNEL::NORM_POLYGON:
8179 std::back_insert_iterator< std::vector<int> > ii(ret);
8180 std::copy(connBg+1,connEnd,ii);
8182 std::reverse_iterator<const int *> rConnBg(connEnd);
8183 std::reverse_iterator<const int *> rConnEnd(connBg+1);
8184 std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8185 std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8186 for(std::size_t i=0;i<nbOfRadFaces;i++)
8189 int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8190 std::copy(conn,conn+4,ii);
8195 throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8200 * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8202 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8205 double v[3]={0.,0.,0.};
8206 std::size_t sz=std::distance(begin,end);
8211 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];
8212 v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8213 v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8215 double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8217 // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8218 // SEG3 forming a circle):
8219 if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8221 v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8222 for(std::size_t j=0;j<sz;j++)
8224 if (j%2) // current point i is quadratic, next point i+1 is standard
8227 ip1 = (j+1)%sz; // ip1 = "i+1"
8229 else // current point i is standard, next point i+1 is quadratic
8234 v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8235 v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8236 v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8238 ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8244 * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8246 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8248 std::vector<std::pair<int,int> > edges;
8249 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8250 const int *bgFace=begin;
8251 for(std::size_t i=0;i<nbOfFaces;i++)
8253 const int *endFace=std::find(bgFace+1,end,-1);
8254 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8255 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8257 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8258 if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8260 edges.push_back(p1);
8264 return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8268 * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8270 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8272 double vec0[3],vec1[3];
8273 std::size_t sz=std::distance(begin,end);
8275 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8276 int nbOfNodes=(int)sz/2;
8277 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8278 const double *pt0=coords+3*begin[0];
8279 const double *pt1=coords+3*begin[nbOfNodes];
8280 vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8281 return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8284 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8286 std::size_t sz=std::distance(begin,end);
8287 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8288 std::size_t nbOfNodes(sz/2);
8289 std::copy(begin,end,(int *)tmp);
8290 for(std::size_t j=1;j<nbOfNodes;j++)
8292 begin[j]=tmp[nbOfNodes-j];
8293 begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8297 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8299 std::size_t sz=std::distance(begin,end);
8301 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8302 double vec0[3],vec1[3];
8303 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8304 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];
8305 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;
8308 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8310 std::size_t sz=std::distance(begin,end);
8312 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8314 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8315 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8316 return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8320 * 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 )
8321 * 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
8324 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8325 * \param [in] coords the coordinates with nb of components exactly equal to 3
8326 * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8327 * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8328 * \param [out] res the result is put at the end of the vector without any alteration of the data.
8330 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8332 int nbFaces=std::count(begin+1,end,-1)+1;
8333 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8334 double *vPtr=v->getPointer();
8335 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8336 double *pPtr=p->getPointer();
8337 const int *stFaceConn=begin+1;
8338 for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8340 const int *endFaceConn=std::find(stFaceConn,end,-1);
8341 ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8342 stFaceConn=endFaceConn+1;
8344 pPtr=p->getPointer(); vPtr=v->getPointer();
8345 DataArrayInt *comm1=0,*commI1=0;
8346 v->findCommonTuples(eps,-1,comm1,commI1);
8347 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8348 const int *comm1Ptr=comm1->getConstPointer();
8349 const int *commI1Ptr=commI1->getConstPointer();
8350 int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8351 res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8353 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8354 mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8355 mm->finishInsertingCells();
8357 for(int i=0;i<nbOfGrps1;i++)
8359 int vecId=comm1Ptr[commI1Ptr[i]];
8360 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8361 DataArrayInt *comm2=0,*commI2=0;
8362 tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8363 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8364 const int *comm2Ptr=comm2->getConstPointer();
8365 const int *commI2Ptr=commI2->getConstPointer();
8366 int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8367 for(int j=0;j<nbOfGrps2;j++)
8369 if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8371 res->insertAtTheEnd(begin,end);
8372 res->pushBackSilent(-1);
8376 int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8377 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8378 ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8379 DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8380 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8381 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8382 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8383 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8384 const int *idsNodePtr=idsNode->getConstPointer();
8385 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];
8386 double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8387 double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8388 if(std::abs(norm)>eps)
8390 double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8391 mm3->rotate(center,vec,angle);
8393 mm3->changeSpaceDimension(2);
8394 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8395 const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8396 const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8397 int nbOfCells=mm4->getNumberOfCells();
8398 for(int k=0;k<nbOfCells;k++)
8401 for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8402 res->pushBackSilent(idsNodePtr[*work]);
8403 res->pushBackSilent(-1);
8408 res->popBackSilent();
8412 * 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
8413 * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8415 * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8416 * \param [in] coords coordinates expected to have 3 components.
8417 * \param [in] begin start of the nodal connectivity of the face.
8418 * \param [in] end end of the nodal connectivity (excluded) of the face.
8419 * \param [out] v the normalized vector of size 3
8420 * \param [out] p the pos of plane
8422 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8424 std::size_t nbPoints=std::distance(begin,end);
8426 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8427 double vec[3]={0.,0.,0.};
8429 bool refFound=false;
8430 for(;j<nbPoints-1 && !refFound;j++)
8432 vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8433 vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8434 vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8435 double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8439 vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8442 for(std::size_t i=j;i<nbPoints-1;i++)
8445 curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8446 curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8447 curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8448 double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8451 curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8452 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];
8453 norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8456 v[0]/=norm; v[1]/=norm; v[2]/=norm;
8457 *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8461 throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8465 * This method tries to obtain a well oriented polyhedron.
8466 * If the algorithm fails, an exception will be thrown.
8468 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8470 std::list< std::pair<int,int> > edgesOK,edgesFinished;
8471 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8472 std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8474 int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8475 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8476 for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8478 while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8481 std::size_t smthChanged=0;
8482 for(std::size_t i=0;i<nbOfFaces;i++)
8484 endFace=std::find(bgFace+1,end,-1);
8485 nbOfEdgesInFace=std::distance(bgFace,endFace);
8489 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8491 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8492 std::pair<int,int> p2(p1.second,p1.first);
8493 bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8494 bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8495 if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8500 std::reverse(bgFace+1,endFace);
8501 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8503 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8504 std::pair<int,int> p2(p1.second,p1.first);
8505 if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8506 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8507 if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8508 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8509 std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8510 if(it!=edgesOK.end())
8513 edgesFinished.push_back(p1);
8516 edgesOK.push_back(p1);
8523 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8525 if(!edgesOK.empty())
8526 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8527 if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8528 {//not lucky ! The first face was not correctly oriented : reorient all faces...
8530 for(std::size_t i=0;i<nbOfFaces;i++)
8532 endFace=std::find(bgFace+1,end,-1);
8533 std::reverse(bgFace+1,endFace);
8539 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8541 int nbOfNodesExpected(skin->getNumberOfNodes());
8542 const int *n2oPtr(n2o->getConstPointer());
8543 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8544 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8545 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8546 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8547 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8548 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8549 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_POLYGON;
8550 if(nbOfNodesExpected<1)
8552 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8553 *work++=n2oPtr[prevNode];
8554 for(int i=1;i<nbOfNodesExpected;i++)
8556 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8558 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8559 conn.erase(prevNode);
8562 int curNode(*(conn.begin()));
8563 *work++=n2oPtr[curNode];
8564 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8565 shar.erase(prevCell);
8568 prevCell=*(shar.begin());
8572 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8575 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8578 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8583 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8585 int nbOfNodesExpected(skin->getNumberOfNodes());
8586 int nbOfTurn(nbOfNodesExpected/2);
8587 const int *n2oPtr(n2o->getConstPointer());
8588 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8589 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8590 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8591 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8592 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8593 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8594 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_QPOLYG;
8595 if(nbOfNodesExpected<1)
8597 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8598 *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8599 for(int i=1;i<nbOfTurn;i++)
8601 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8603 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8604 conn.erase(prevNode);
8607 int curNode(*(conn.begin()));
8608 *work=n2oPtr[curNode];
8609 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8610 shar.erase(prevCell);
8613 int curCell(*(shar.begin()));
8614 work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8620 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8623 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8626 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8632 * This method makes the assumption spacedimension == meshdimension == 2.
8633 * This method works only for linear cells.
8635 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8637 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8639 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8640 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8641 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8642 int oldNbOfNodes(skin->getNumberOfNodes());
8643 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8644 int nbOfNodesExpected(skin->getNumberOfNodes());
8645 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8646 int nbCells(skin->getNumberOfCells());
8647 if(nbCells==nbOfNodesExpected)
8648 return buildUnionOf2DMeshLinear(skin,n2o);
8649 else if(2*nbCells==nbOfNodesExpected)
8650 return buildUnionOf2DMeshQuadratic(skin,n2o);
8652 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8656 * This method makes the assumption spacedimension == meshdimension == 3.
8657 * This method works only for linear cells.
8659 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8661 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8663 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8664 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8665 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8666 const int *conn=m->getNodalConnectivity()->getConstPointer();
8667 const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8668 int nbOfCells=m->getNumberOfCells();
8669 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8670 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED;
8673 work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8674 for(int i=1;i<nbOfCells;i++)
8677 work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8683 * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8684 * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8686 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8690 for(int i=0;i<nbOfNodesInCell;i++)
8691 w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8692 else if(spaceDim==2)
8694 for(int i=0;i<nbOfNodesInCell;i++)
8696 w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8701 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8704 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8706 int nbOfCells=getNumberOfCells();
8708 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8709 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};
8710 ofs << " <" << getVTKDataSetType() << ">\n";
8711 ofs << " <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8712 ofs << " <PointData>\n" << pointData << std::endl;
8713 ofs << " </PointData>\n";
8714 ofs << " <CellData>\n" << cellData << std::endl;
8715 ofs << " </CellData>\n";
8716 ofs << " <Points>\n";
8717 if(getSpaceDimension()==3)
8718 _coords->writeVTK(ofs,8,"Points",byteData);
8721 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8722 coo->writeVTK(ofs,8,"Points",byteData);
8724 ofs << " </Points>\n";
8725 ofs << " <Cells>\n";
8726 const int *cPtr=_nodal_connec->getConstPointer();
8727 const int *cIPtr=_nodal_connec_index->getConstPointer();
8728 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8729 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8730 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8731 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8732 int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8733 int szFaceOffsets=0,szConn=0;
8734 for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8737 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8740 *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8741 w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8745 int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8746 *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8747 std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8748 *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8749 w4=std::copy(c.begin(),c.end(),w4);
8752 types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8753 types->writeVTK(ofs,8,"UInt8","types",byteData);
8754 offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8755 if(szFaceOffsets!=0)
8756 {//presence of Polyhedra
8757 connectivity->reAlloc(szConn);
8758 faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8759 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8760 w1=faces->getPointer();
8761 for(int i=0;i<nbOfCells;i++)
8762 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8764 int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8766 const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8767 for(int j=0;j<nbFaces;j++)
8769 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8770 *w1++=(int)std::distance(w6,w5);
8771 w1=std::copy(w6,w5,w1);
8775 faces->writeVTK(ofs,8,"Int32","faces",byteData);
8777 connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8778 ofs << " </Cells>\n";
8779 ofs << " </Piece>\n";
8780 ofs << " </" << getVTKDataSetType() << ">\n";
8783 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8785 stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8787 { stream << " Not set !"; return ; }
8788 stream << " Mesh dimension : " << _mesh_dim << ".";
8792 { stream << " No coordinates set !"; return ; }
8793 if(!_coords->isAllocated())
8794 { stream << " Coordinates set but not allocated !"; return ; }
8795 stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8796 stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8797 if(!_nodal_connec_index)
8798 { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8799 if(!_nodal_connec_index->isAllocated())
8800 { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8801 int lgth=_nodal_connec_index->getNumberOfTuples();
8802 int cpt=_nodal_connec_index->getNumberOfComponents();
8803 if(cpt!=1 || lgth<1)
8805 stream << std::endl << "Number of cells : " << lgth-1 << ".";
8808 std::string MEDCouplingUMesh::getVTKDataSetType() const
8810 return std::string("UnstructuredGrid");
8813 std::string MEDCouplingUMesh::getVTKFileExtension() const
8815 return std::string("vtu");
8819 * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8820 * returns a result mesh constituted by polygons.
8821 * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8822 * all nodes from m2.
8823 * The meshes should be in 2D space. In
8824 * addition, returns two arrays mapping cells of the result mesh to cells of the input
8826 * \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
8827 * 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)
8828 * \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
8829 * 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)
8830 * \param [in] eps - precision used to detect coincident mesh entities.
8831 * \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8832 * cell an id of the cell of \a m1 it comes from. The caller is to delete
8833 * this array using decrRef() as it is no more needed.
8834 * \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8835 * cell an id of the cell of \a m2 it comes from. -1 value means that a
8836 * result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8837 * any cell of \a m2. The caller is to delete this array using decrRef() as
8838 * it is no more needed.
8839 * \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8840 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8841 * is no more needed.
8842 * \throw If the coordinates array is not set in any of the meshes.
8843 * \throw If the nodal connectivity of cells is not defined in any of the meshes.
8844 * \throw If any of the meshes is not a 2D mesh in 2D space.
8846 * \sa conformize2D, mergeNodes
8848 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8849 double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8852 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
8853 m1->checkFullyDefined();
8854 m2->checkFullyDefined();
8855 if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8856 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!");
8858 // Step 1: compute all edge intersections (new nodes)
8859 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8860 MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
8861 DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8862 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
8863 IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
8864 m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8865 addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
8866 revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8867 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8868 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8870 // Step 2: re-order newly created nodes according to the ordering found in m2
8871 std::vector< std::vector<int> > intersectEdge2;
8872 BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8873 subDiv2.clear(); dd5=0; dd6=0;
8876 std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8877 std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8878 BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8879 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8881 // Step 4: Prepare final result:
8882 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
8883 addCooDa->alloc((int)(addCoo.size())/2,2);
8884 std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8885 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
8886 addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8887 std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8888 std::vector<const DataArrayDouble *> coordss(4);
8889 coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8890 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
8891 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
8892 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8893 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8894 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8895 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8896 ret->setConnectivity(conn,connI,true);
8897 ret->setCoords(coo);
8898 cellNb1=c1.retn(); cellNb2=c2.retn();
8904 bool IsColinearOfACellOf(const std::vector< std::vector<int> >& intersectEdge1, const std::vector<int>& candidates, int start, int stop, int& retVal)
8906 if(candidates.empty())
8908 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
8910 const std::vector<int>& pool(intersectEdge1[*it]);
8911 int tmp[2]; tmp[0]=start; tmp[1]=stop;
8912 if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
8917 tmp[0]=stop; tmp[1]=start;
8918 if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
8927 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,
8928 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInRetColinear, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInMesh1DForIdsInRetColinear)
8930 idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1);
8931 idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1);
8932 int nCells(mesh1D->getNumberOfCells());
8933 if(nCells!=(int)intersectEdge2.size())
8934 throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
8935 const DataArrayDouble *coo2(mesh1D->getCoords());
8936 const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
8937 const double *coo2Ptr(coo2->begin());
8938 int offset1(coords1->getNumberOfTuples());
8939 int offset2(offset1+coo2->getNumberOfTuples());
8940 int offset3(offset2+addCoo.size()/2);
8941 std::vector<double> addCooQuad;
8942 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
8943 int tmp[4],cicnt(0),kk(0);
8944 for(int i=0;i<nCells;i++)
8946 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
8947 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
8948 const std::vector<int>& subEdges(intersectEdge2[i]);
8949 int nbSubEdge(subEdges.size()/2);
8950 for(int j=0;j<nbSubEdge;j++,kk++)
8952 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));
8953 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
8954 INTERP_KERNEL::Edge *e2Ptr(e2);
8955 std::map<int,int>::const_iterator itm;
8956 if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
8958 tmp[0]=INTERP_KERNEL::NORM_SEG3;
8959 itm=mergedNodes.find(subEdges[2*j]);
8960 tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
8961 itm=mergedNodes.find(subEdges[2*j+1]);
8962 tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
8963 tmp[3]=offset3+(int)addCooQuad.size()/2;
8965 e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2);
8967 cOut->insertAtTheEnd(tmp,tmp+4);
8968 ciOut->pushBackSilent(cicnt);
8972 tmp[0]=INTERP_KERNEL::NORM_SEG2;
8973 itm=mergedNodes.find(subEdges[2*j]);
8974 tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
8975 itm=mergedNodes.find(subEdges[2*j+1]);
8976 tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
8978 cOut->insertAtTheEnd(tmp,tmp+3);
8979 ciOut->pushBackSilent(cicnt);
8982 if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00))
8984 idsInRetColinear->pushBackSilent(kk);
8985 idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00);
8990 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
8991 ret->setConnectivity(cOut,ciOut,true);
8992 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr3(DataArrayDouble::New());
8993 arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
8994 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
8995 std::vector<const DataArrayDouble *> coordss(4);
8996 coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
8997 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
8998 ret->setCoords(arr);
9002 MEDCouplingUMesh *BuildRefined2DCellLinear(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9004 std::vector<int> allEdges;
9005 for(const int *it2(descBg);it2!=descEnd;it2++)
9007 const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9009 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9011 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9013 std::size_t nb(allEdges.size());
9015 throw INTERP_KERNEL::Exception("BuildRefined2DCellLinear : internal error 1 !");
9016 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9017 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9018 ret->setCoords(coords);
9019 ret->allocateCells(1);
9020 std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9021 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9022 connOut[kk]=allEdges[2*kk];
9023 ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]);
9027 MEDCouplingUMesh *BuildRefined2DCellQuadratic(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9029 const int *c(mesh2D->getNodalConnectivity()->begin()),*ci(mesh2D->getNodalConnectivityIndex()->begin());
9030 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[cellIdInMesh2D]]));
9032 unsigned sz(cm.getNumberOfSons2(c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1));
9033 if(sz!=std::distance(descBg,descEnd))
9034 throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 1 !");
9035 INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]]);
9036 std::vector<int> allEdges,centers;
9037 const double *coordsPtr(coords->begin());
9038 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
9039 int offset(coords->getNumberOfTuples());
9040 for(const int *it2(descBg);it2!=descEnd;it2++,ii++)
9042 INTERP_KERNEL::NormalizedCellType typeOfSon;
9043 cm.fillSonCellNodalConnectivity2(ii,c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1,tmpPtr,typeOfSon);
9044 const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9046 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9048 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9050 centers.push_back(tmpPtr[2]);//special case where no subsplit of edge -> reuse the original center.
9052 {//the current edge has been subsplit -> create corresponding centers.
9053 std::size_t nbOfCentersToAppend(edge1.size()/2);
9054 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9055 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpPtr,coordsPtr,m));
9056 std::vector<int>::const_iterator it3(allEdges.end()-edge1.size());
9057 for(std::size_t k=0;k<nbOfCentersToAppend;k++)
9060 const double *aa(coordsPtr+2*(*it3++));
9061 const double *bb(coordsPtr+2*(*it3++));
9062 ee->getMiddleOfPoints(aa,bb,tmpp);
9063 addCoo->insertAtTheEnd(tmpp,tmpp+2);
9064 centers.push_back(offset+k);
9068 std::size_t nb(allEdges.size());
9070 throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 2 !");
9071 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9072 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9074 ret->setCoords(coords);
9077 addCoo->rearrange(2);
9078 addCoo=DataArrayDouble::Aggregate(coords,addCoo);
9079 ret->setCoords(addCoo);
9081 ret->allocateCells(1);
9082 std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9083 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9084 connOut[kk]=allEdges[2*kk];
9085 connOut.insert(connOut.end(),centers.begin(),centers.end());
9086 ret->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,connOut.size(),&connOut[0]);
9091 * This method creates a refinement of a cell in \a mesh2D. Those cell is defined by descending connectivity and the sorted subdivided nodal connectivity
9094 * \param [in] mesh2D - The origin 2D mesh. \b Warning \b coords are not those of \a mesh2D. But mesh2D->getCoords()==coords[:mesh2D->getNumberOfNodes()]
9096 MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9098 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(mesh2D->getTypeOfCell(cellIdInMesh2D)));
9099 if(!cm.isQuadratic())
9100 return BuildRefined2DCellLinear(coords,descBg,descEnd,intersectEdge1);
9102 return BuildRefined2DCellQuadratic(coords,mesh2D,cellIdInMesh2D,descBg,descEnd,intersectEdge1);
9105 void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector<int>& conn, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edges)
9108 for(std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >::const_iterator it=edges.begin();it!=edges.end();it++)
9110 const INTERP_KERNEL::Edge *ee(*it);
9111 if(dynamic_cast<const INTERP_KERNEL::EdgeArcCircle *>(ee))
9115 mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]);
9118 const double *coo(mesh2D->getCoords()->begin());
9119 std::size_t sz(conn.size());
9120 std::vector<double> addCoo;
9121 std::vector<int> conn2(conn);
9122 int offset(mesh2D->getNumberOfNodes());
9123 for(std::size_t i=0;i<sz;i++)
9126 edges[(i+1)%sz]->getMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);// tony a chier i+1 -> i
9127 addCoo.insert(addCoo.end(),tmp,tmp+2);
9128 conn2.push_back(offset+(int)i);
9130 mesh2D->getCoords()->rearrange(1);
9131 mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size());
9132 mesh2D->getCoords()->rearrange(2);
9133 mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]);
9138 * \b WARNING edges in out1 coming from \a splitMesh1D are \b NOT oriented because only used for equation of curve.
9140 * This method cuts in 2 parts the input 2D cell given using boundaries description (\a edge1Bis and \a edge1BisPtr) using
9141 * a set of edges defined in \a splitMesh1D.
9143 void BuildMesh2DCutInternal2(const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& edge1Bis, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edge1BisPtr,
9144 std::vector< std::vector<int> >& out0, std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& out1)
9146 std::size_t nb(edge1Bis.size()/2);
9147 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9148 int iEnd(splitMesh1D->getNumberOfCells());
9150 throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal2 : internal error ! input 1D mesh must have at least one cell !");
9152 const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9153 for(ii=0;ii<nb && edge1Bis[2*ii]!=cSplitPtr[ciSplitPtr[0]+1];ii++);
9154 for(jj=ii;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd-1]+2];jj++);
9157 {//the edges splitMesh1D[iStart:iEnd] does not fully cut the current 2D cell -> single output cell
9158 out0.resize(1); out1.resize(1);
9159 std::vector<int>& connOut(out0[0]);
9160 connOut.resize(nbOfEdgesOf2DCellSplit);
9161 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr(out1[0]);
9162 edgesPtr.resize(nbOfEdgesOf2DCellSplit);
9163 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9165 connOut[kk]=edge1Bis[2*kk];
9166 edgesPtr[kk]=edge1BisPtr[2*kk];
9171 // [i,iEnd[ contains the
9172 out0.resize(2); out1.resize(2);
9173 std::vector<int>& connOutLeft(out0[0]);
9174 std::vector<int>& connOutRight(out0[1]);//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1]
9175 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eleft(out1[0]);
9176 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eright(out1[1]);
9177 for(std::size_t k=ii;k<jj+1;k++)
9178 { connOutLeft.push_back(edge1Bis[2*k+1]); eleft.push_back(edge1BisPtr[2*k+1]); }
9179 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > ees(iEnd);
9180 for(int ik=0;ik<iEnd;ik++)
9182 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9183 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9186 for(int ik=iEnd-1;ik>=0;ik--)
9187 connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]);
9188 for(std::size_t k=jj+1;k<nbOfEdgesOf2DCellSplit+ii;k++)
9189 { connOutRight.push_back(edge1Bis[2*k+1]); eright.push_back(edge1BisPtr[2*k+1]); }
9190 eleft.insert(eleft.end(),ees.rbegin(),ees.rend());
9191 for(int ik=0;ik<iEnd;ik++)
9192 connOutRight.push_back(cSplitPtr[ciSplitPtr[ik]+2]);
9193 eright.insert(eright.end(),ees.begin(),ees.end());
9205 CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9207 std::vector<int> _edges;
9208 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > _edges_ptr;
9211 CellInfo::CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr)
9213 std::size_t nbe(edges.size());
9214 std::vector<int> edges2(2*nbe); std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edgesPtr2(2*nbe);
9215 for(std::size_t i=0;i<nbe;i++)
9217 edges2[2*i]=edges[i]; edges2[2*i+1]=edges[(i+1)%nbe];
9218 edgesPtr2[2*i]=edgesPtr[(i+1)%nbe]; edgesPtr2[2*i+1]=edgesPtr[(i+1)%nbe];//tony a chier
9220 _edges.resize(4*nbe); _edges_ptr.resize(4*nbe);
9221 std::copy(edges2.begin(),edges2.end(),_edges.begin()); std::copy(edges2.begin(),edges2.end(),_edges.begin()+2*nbe);
9222 std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()); std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()+2*nbe);
9228 EdgeInfo(int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh):_istart(istart),_iend(iend),_mesh(mesh),_left(-7),_right(-7) { }
9229 EdgeInfo(int istart, int iend, int pos, const MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge>& edge):_istart(istart),_iend(iend),_edge(edge),_left(pos),_right(pos+1) { }
9230 bool isInMyRange(int pos) const { return pos>=_istart && pos<_iend; }
9231 void somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9232 void feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const;
9236 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _mesh;
9237 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> _edge;
9242 void EdgeInfo::somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9244 const MEDCouplingUMesh *mesh(_mesh);
9250 { _left++; _right++; return ; }
9253 bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9254 if((isLeft && isRight) || (!isLeft && !isRight))
9255 throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 1 !");
9266 bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9267 if((isLeft && isRight) || (!isLeft && !isRight))
9268 throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 2 !");
9283 void EdgeInfo::feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const
9285 const MEDCouplingUMesh *mesh(_mesh);
9288 neighbors[0]=offset+_left; neighbors[1]=offset+_right;
9291 {// not fully splitting cell case
9292 if(mesh2D->getNumberOfCells()==1)
9293 {//little optimization. 1 cell no need to find in which cell mesh is !
9294 neighbors[0]=offset; neighbors[1]=offset;
9299 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9300 int cellId(mesh2D->getCellContainingPoint(barys->begin(),eps));
9302 throw INTERP_KERNEL::Exception("EdgeInfo::feedEdgeInfoAt : internal error !");
9303 neighbors[0]=offset+cellId; neighbors[1]=offset+cellId;
9308 class VectorOfCellInfo
9311 VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9312 std::size_t size() const { return _pool.size(); }
9313 int getPositionOf(double eps, const MEDCouplingUMesh *mesh) const;
9314 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);
9315 const std::vector<int>& getConnOf(int pos) const { return get(pos)._edges; }
9316 const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& getEdgePtrOf(int pos) const { return get(pos)._edges_ptr; }
9317 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> getZeMesh() const { return _ze_mesh; }
9318 void feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const;
9320 int getZePosOfEdgeGivenItsGlobalId(int pos) const;
9321 void updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9322 const CellInfo& get(int pos) const;
9323 CellInfo& get(int pos);
9325 std::vector<CellInfo> _pool;
9326 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _ze_mesh;
9327 std::vector<EdgeInfo> _edge_info;
9330 VectorOfCellInfo::VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr):_pool(1)
9332 _pool[0]._edges=edges;
9333 _pool[0]._edges_ptr=edgesPtr;
9336 int VectorOfCellInfo::getPositionOf(double eps, const MEDCouplingUMesh *mesh) const
9339 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : empty !");
9342 const MEDCouplingUMesh *zeMesh(_ze_mesh);
9344 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : null aggregated mesh !");
9345 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9346 return zeMesh->getCellContainingPoint(barys->begin(),eps);
9349 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)
9351 get(pos);//to check pos
9352 bool isFast(pos==0 && _pool.size()==1);
9353 std::size_t sz(edges.size());
9354 // dealing with edges
9356 _edge_info.push_back(EdgeInfo(istart,iend,mesh1DInCase));
9358 _edge_info.push_back(EdgeInfo(istart,iend,pos,edgePtrs[0].back()));
9360 std::vector<CellInfo> pool(_pool.size()-1+sz);
9361 for(int i=0;i<pos;i++)
9363 for(std::size_t j=0;j<sz;j++)
9364 pool[pos+j]=CellInfo(edges[j],edgePtrs[j]);
9365 for(int i=pos+1;i<(int)_pool.size();i++)
9366 pool[i+sz-1]=_pool[i];
9370 updateEdgeInfo(pos,edgePtrs[0],edgePtrs[1]);
9378 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > ms;
9381 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(0,pos,true)));
9385 if(pos<_ze_mesh->getNumberOfCells()-1)
9387 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(pos+1,_ze_mesh->getNumberOfCells(),true)));
9390 std::vector< const MEDCouplingUMesh *> ms2(ms.size());
9391 for(std::size_t j=0;j<ms2.size();j++)
9393 _ze_mesh=MEDCouplingUMesh::MergeUMeshesOnSameCoords(ms2);
9396 void VectorOfCellInfo::feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const
9398 _edge_info[getZePosOfEdgeGivenItsGlobalId(pos)].feedEdgeInfoAt(eps,_ze_mesh,offset,neighbors);
9401 int VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId(int pos) const
9404 throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id ! Must be >=0 !");
9406 for(std::vector<EdgeInfo>::const_iterator it=_edge_info.begin();it!=_edge_info.end();it++,ret++)
9408 if((*it).isInMyRange(pos))
9411 throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id !");
9414 void VectorOfCellInfo::updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9416 get(pos);//to check;
9417 if(_edge_info.empty())
9419 std::size_t sz(_edge_info.size()-1);
9420 for(std::size_t i=0;i<sz;i++)
9421 _edge_info[i].somethingHappendAt(pos,newLeft,newRight);
9424 const CellInfo& VectorOfCellInfo::get(int pos) const
9426 if(pos<0 || pos>=(int)_pool.size())
9427 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get const : invalid pos !");
9431 CellInfo& VectorOfCellInfo::get(int pos)
9433 if(pos<0 || pos>=(int)_pool.size())
9434 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get : invalid pos !");
9440 * - a \b closed set of edges ( \a allEdges and \a allEdgesPtr ) that defines the split descending 2D cell.
9441 * - \a splitMesh1D a split 2D curve mesh contained into 2D cell defined above.
9443 * This method returns the 2D mesh and feeds \a idsLeftRight using offset.
9445 * Algorithm : \a splitMesh1D is cut into contiguous parts. Each contiguous parts will build incrementally the output 2D cells.
9447 * \param [in] allEdges a list of pairs (beginNode, endNode). Linked with \a allEdgesPtr to get the equation of edge.
9449 MEDCouplingUMesh *BuildMesh2DCutInternal(double eps, const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& allEdges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& allEdgesPtr, int offset,
9450 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9452 int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells());
9453 if(nbCellsInSplitMesh1D==0)
9454 throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal : internal error ! input 1D mesh must have at least one cell !");
9455 const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9456 std::size_t nb(allEdges.size()),jj;
9458 throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !");
9459 std::vector<int> edge1Bis(nb*2);
9460 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edge1BisPtr(nb*2);
9461 std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin());
9462 std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb);
9463 std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin());
9464 std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb);
9466 idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(nbCellsInSplitMesh1D*2); idsLeftRight->fillWithValue(-2); idsLeftRight->rearrange(2);
9467 int *idsLeftRightPtr(idsLeftRight->getPointer());
9468 VectorOfCellInfo pool(edge1Bis,edge1BisPtr);
9469 for(int iStart=0;iStart<nbCellsInSplitMesh1D;)
9470 {// split [0:nbCellsInSplitMesh1D) in contiguous parts [iStart:iEnd)
9472 for(;iEnd<nbCellsInSplitMesh1D;)
9474 for(jj=0;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd]+2];jj++);
9480 if(iEnd<nbCellsInSplitMesh1D)
9483 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfSplitMesh1D(static_cast<MEDCouplingUMesh *>(splitMesh1D->buildPartOfMySelf2(iStart,iEnd,1,true)));
9484 int pos(pool.getPositionOf(eps,partOfSplitMesh1D));
9486 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>retTmp(MEDCouplingUMesh::New("",2));
9487 retTmp->setCoords(splitMesh1D->getCoords());
9488 retTmp->allocateCells();
9490 std::vector< std::vector<int> > out0;
9491 std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > > out1;
9493 BuildMesh2DCutInternal2(partOfSplitMesh1D,pool.getConnOf(pos),pool.getEdgePtrOf(pos),out0,out1);
9494 for(std::size_t cnt=0;cnt<out0.size();cnt++)
9495 AddCellInMesh2D(retTmp,out0[cnt],out1[cnt]);
9496 pool.setMeshAt(pos,retTmp,iStart,iEnd,partOfSplitMesh1D,out0,out1);
9500 for(int mm=0;mm<nbCellsInSplitMesh1D;mm++)
9501 pool.feedEdgeInfoAt(eps,mm,offset,idsLeftRightPtr+2*mm);
9502 return pool.getZeMesh().retn();
9505 MEDCouplingUMesh *BuildMesh2DCutFrom(double eps, int cellIdInMesh2D, const MEDCouplingUMesh *mesh2DDesc, const MEDCouplingUMesh *splitMesh1D,
9506 const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1, int offset,
9507 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9509 const int *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin());
9511 std::vector<int> allEdges;
9512 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > allEdgesPtr; // for each sub edge in splitMesh2D the uncut Edge object of the original mesh2D
9513 for(const int *it(descBg);it!=descEnd;it++) // for all edges in the descending connectivity of the 2D mesh in relative Fortran mode
9515 int edgeId(std::abs(*it)-1);
9516 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9517 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m));
9518 const std::vector<int>& edge1(intersectEdge1[edgeId]);
9520 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9522 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9523 std::size_t sz(edge1.size());
9524 for(std::size_t cnt=0;cnt<sz;cnt++)
9525 allEdgesPtr.push_back(ee);
9528 return BuildMesh2DCutInternal(eps,splitMesh1D,allEdges,allEdgesPtr,offset,idsLeftRight);
9531 bool AreEdgeEqual(const double *coo2D, const INTERP_KERNEL::CellModel& typ1, const int *conn1, const INTERP_KERNEL::CellModel& typ2, const int *conn2, double eps)
9533 if(!typ1.isQuadratic() && !typ2.isQuadratic())
9534 {//easy case comparison not
9535 return conn1[0]==conn2[0] && conn1[1]==conn2[1];
9537 else if(typ1.isQuadratic() && typ2.isQuadratic())
9539 bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9542 if(conn1[2]==conn2[2])
9544 const double *a(coo2D+2*conn1[2]),*b(coo2D+2*conn2[2]);
9545 double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9549 {//only one is quadratic
9550 bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9553 const double *a(0),*bb(0),*be(0);
9554 if(typ1.isQuadratic())
9556 a=coo2D+2*conn1[2]; bb=coo2D+2*conn2[0]; be=coo2D+2*conn2[1];
9560 a=coo2D+2*conn2[2]; bb=coo2D+2*conn1[0]; be=coo2D+2*conn1[1];
9562 double b[2]; b[0]=(be[0]+bb[0])/2.; b[1]=(be[1]+bb[1])/2.;
9563 double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9569 * This method returns among the cellIds [ \a candidatesIn2DBg , \a candidatesIn2DEnd ) in \a mesh2DSplit those exactly sharing \a cellIdInMesh1DSplitRelative in \a mesh1DSplit.
9570 * \a mesh2DSplit and \a mesh1DSplit are expected to share the coordinates array.
9572 * \param [in] cellIdInMesh1DSplitRelative is in Fortran mode using sign to specify direction.
9574 int FindRightCandidateAmong(const MEDCouplingUMesh *mesh2DSplit, const int *candidatesIn2DBg, const int *candidatesIn2DEnd, const MEDCouplingUMesh *mesh1DSplit, int cellIdInMesh1DSplitRelative, double eps)
9576 if(candidatesIn2DEnd==candidatesIn2DBg)
9577 throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 1 !");
9578 const double *coo(mesh2DSplit->getCoords()->begin());
9579 if(std::distance(candidatesIn2DBg,candidatesIn2DEnd)==1)
9580 return *candidatesIn2DBg;
9581 int edgeId(std::abs(cellIdInMesh1DSplitRelative)-1);
9582 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur1D(static_cast<MEDCouplingUMesh *>(mesh1DSplit->buildPartOfMySelf(&edgeId,&edgeId+1,true)));
9583 if(cellIdInMesh1DSplitRelative<0)
9584 cur1D->changeOrientationOfCells();
9585 const int *c1D(cur1D->getNodalConnectivity()->begin());
9586 const INTERP_KERNEL::CellModel& ref1DType(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c1D[0]));
9587 for(const int *it=candidatesIn2DBg;it!=candidatesIn2DEnd;it++)
9589 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur2D(static_cast<MEDCouplingUMesh *>(mesh2DSplit->buildPartOfMySelf(it,it+1,true)));
9590 const int *c(cur2D->getNodalConnectivity()->begin()),*ci(cur2D->getNodalConnectivityIndex()->begin());
9591 const INTERP_KERNEL::CellModel &cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[0]]));
9592 unsigned sz(cm.getNumberOfSons2(c+ci[0]+1,ci[1]-ci[0]-1));
9593 INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[1]-ci[0]]);
9594 for(unsigned it2=0;it2<sz;it2++)
9596 INTERP_KERNEL::NormalizedCellType typeOfSon;
9597 cm.fillSonCellNodalConnectivity2(it2,c+ci[0]+1,ci[1]-ci[0]-1,tmpPtr,typeOfSon);
9598 const INTERP_KERNEL::CellModel &curCM(INTERP_KERNEL::CellModel::GetCellModel(typeOfSon));
9599 if(AreEdgeEqual(coo,ref1DType,c1D+1,curCM,tmpPtr,eps))
9603 throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 2 ! Unable to find the edge among split cell !");
9609 * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
9610 * 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
9611 * and finaly, in case of quadratic polygon the centers of edges new nodes.
9612 * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
9614 * \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
9615 * 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)
9616 * \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
9617 * you can invoke orderConsecutiveCells1D on \a mesh1D.
9618 * \param [in] eps - precision used to perform intersections and localization operations.
9619 * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
9620 * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
9621 * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
9622 * 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.
9623 * \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
9624 * and the cell in \a splitMesh2D on the right for the 2nt component. -1 means no cell.
9625 * 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.
9627 * \sa Intersect2DMeshes, orderConsecutiveCells1D, conformize2D, mergeNodes
9629 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
9631 if(!mesh2D || !mesh1D)
9632 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
9633 mesh2D->checkFullyDefined();
9634 mesh1D->checkFullyDefined();
9635 const std::vector<std::string>& compNames(mesh2D->getCoords()->getInfoOnComponents());
9636 if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
9637 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
9638 // Step 1: compute all edge intersections (new nodes)
9639 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9640 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
9641 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9642 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9644 // Build desc connectivity
9645 DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
9646 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9647 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
9648 std::map<int,int> mergedNodes;
9649 Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes);
9650 // use mergeNodes to fix intersectEdge1
9651 for(std::vector< std::vector<int> >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++)
9653 std::size_t n((*it0).size()/2);
9654 int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]);
9655 std::map<int,int>::const_iterator it1;
9656 it1=mergedNodes.find(eltStart);
9657 if(it1!=mergedNodes.end())
9658 (*it0)[0]=(*it1).second;
9659 it1=mergedNodes.find(eltEnd);
9660 if(it1!=mergedNodes.end())
9661 (*it0)[2*n-1]=(*it1).second;
9664 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9665 addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9666 // Step 2: re-order newly created nodes according to the ordering found in m2
9667 std::vector< std::vector<int> > intersectEdge2;
9668 BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
9670 // Step 3: compute splitMesh1D
9671 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear;
9672 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2(DataArrayInt::New()); ret2->alloc(0,1);
9673 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1,
9674 idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear));
9675 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(std::numeric_limits<int>::max()); ret3->rearrange(2);
9676 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells()));
9677 // deal with cells in mesh2D that are not cut but only some of their edges are
9678 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCpy());
9679 idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1);
9680 idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique();
9681 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
9682 if(!idsInDesc2DToBeRefined->empty())
9684 DataArrayInt *out0(0),*outi0(0);
9685 MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
9686 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> outi0s(outi0);
9688 out0s=out0s->buildUnique();
9692 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1NonCol(static_cast<MEDCouplingUMesh *>(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end())));
9693 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> baryRet1(ret1NonCol->getBarycenterAndOwner());
9694 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elts,eltsIndex;
9695 mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
9696 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex2(eltsIndex->deltaShiftIndex());
9697 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex3(eltsIndex2->getIdsEqual(1));
9698 if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells())
9699 throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !");
9700 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToBeModified(elts->buildUnique());
9701 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells()));
9702 if((DataArrayInt *)out0s)
9703 untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one
9704 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > outMesh2DSplit;
9705 // OK all is ready to insert in ret2 mesh
9706 if(!untouchedCells->empty())
9707 {// the most easy part, cells in mesh2D not impacted at all
9708 outMesh2DSplit.push_back(static_cast<MEDCouplingUMesh *>(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end())));
9709 outMesh2DSplit.back()->setCoords(ret1->getCoords());
9710 ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end());
9712 if((DataArrayInt *)out0s)
9713 {// here dealing with cells in out0s but not in cellsToBeModified
9714 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fewModifiedCells(out0s->buildSubstraction(cellsToBeModified));
9715 const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin());
9716 for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++)
9718 outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),mesh2D,*it,dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1));
9719 ret1->setCoords(outMesh2DSplit.back()->getCoords());
9721 int offset(ret2->getNumberOfTuples());
9722 ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end());
9723 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1);
9724 partOfRet3->fillWithValue(std::numeric_limits<int>::max()); partOfRet3->rearrange(2);
9725 int kk(0),*ret3ptr(partOfRet3->getPointer());
9726 for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++)
9728 int faceId(std::abs(*it)-1);
9729 for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++)
9731 int tmp(fewModifiedCells->locateValue(*it2));
9734 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9735 ret3ptr[2*kk]=tmp+offset;
9736 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9737 ret3ptr[2*kk+1]=tmp+offset;
9740 {//the current edge is shared by a 2D cell that will be split just after
9741 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9742 ret3ptr[2*kk]=-(*it2+1);
9743 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9744 ret3ptr[2*kk+1]=-(*it2+1);
9748 m1Desc->setCoords(ret1->getCoords());
9749 ret1NonCol->setCoords(ret1->getCoords());
9750 ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true);
9751 if(!outMesh2DSplit.empty())
9753 DataArrayDouble *da(outMesh2DSplit.back()->getCoords());
9754 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> >::iterator itt=outMesh2DSplit.begin();itt!=outMesh2DSplit.end();itt++)
9755 (*itt)->setCoords(da);
9758 cellsToBeModified=cellsToBeModified->buildUniqueNotSorted();
9759 for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++)
9761 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell(elts->getIdsEqual(*it));
9762 idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end());
9763 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end()));
9764 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfMesh1CuttingCur2DCell(static_cast<MEDCouplingUMesh *>(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end())));
9765 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3;
9766 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));
9767 ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true);
9768 outMesh2DSplit.push_back(splitOfOneCell);
9769 for(int i=0;i<splitOfOneCell->getNumberOfCells();i++)
9770 ret2->pushBackSilent(*it);
9773 std::size_t nbOfMeshes(outMesh2DSplit.size());
9774 std::vector<const MEDCouplingUMesh *> tmp(nbOfMeshes);
9775 for(std::size_t i=0;i<nbOfMeshes;i++)
9776 tmp[i]=outMesh2DSplit[i];
9778 ret1->getCoords()->setInfoOnComponents(compNames);
9779 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2D(MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp));
9780 // To finish - filter ret3 - std::numeric_limits<int>::max() -> -1 - negate values must be resolved.
9782 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> edgesToDealWith(ret3->getIdsStrictlyNegative());
9783 for(const int *it=edgesToDealWith->begin();it!=edgesToDealWith->end();it++)
9785 int old2DCellId(-ret3->getIJ(*it,0)-1);
9786 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates(ret2->getIdsEqual(old2DCellId));
9787 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
9789 ret3->replaceOneValByInThis(std::numeric_limits<int>::max(),-1);
9792 splitMesh1D=ret1.retn();
9793 splitMesh2D=ret2D.retn();
9794 cellIdInMesh2D=ret2.retn();
9795 cellIdInMesh1D=ret3.retn();
9799 * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
9800 * (newly created) nodes corresponding to the edge intersections.
9802 * @param[out] cr, crI connectivity of the resulting mesh
9803 * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
9804 * TODO: describe input parameters
9806 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
9807 const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
9808 const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
9809 const std::vector<double>& addCoords,
9810 std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
9812 static const int SPACEDIM=2;
9813 const double *coo1(m1->getCoords()->getConstPointer());
9814 const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer());
9815 int offset1(m1->getNumberOfNodes());
9816 const double *coo2(m2->getCoords()->getConstPointer());
9817 const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer());
9818 int offset2(offset1+m2->getNumberOfNodes());
9819 int offset3(offset2+((int)addCoords.size())/2);
9820 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
9821 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9822 // Here a BBTree on 2D-cells, not on segments:
9823 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
9824 int ncell1(m1->getNumberOfCells());
9826 for(int i=0;i<ncell1;i++)
9828 std::vector<int> candidates2;
9829 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9830 std::map<INTERP_KERNEL::Node *,int> mapp;
9831 std::map<int,INTERP_KERNEL::Node *> mappRev;
9832 INTERP_KERNEL::QuadraticPolygon pol1;
9833 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
9834 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
9835 // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
9836 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
9837 // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
9838 pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
9839 desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
9841 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
9842 std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
9843 INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
9844 for(it1.first();!it1.finished();it1.next())
9845 edges1.insert(it1.current()->getPtr());
9847 std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
9848 std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
9850 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9852 INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
9853 const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
9854 // Complete mapping with elements coming from the current cell it2 in mesh2:
9855 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
9856 // pol2 is the new QP in the final merged result.
9857 pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
9858 pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
9861 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9863 INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
9864 pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
9865 //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
9866 pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9868 // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
9869 // by m2 but that we still want to keep in the final result.
9874 INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9876 catch(INTERP_KERNEL::Exception& e)
9878 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();
9879 throw INTERP_KERNEL::Exception(oss.str().c_str());
9882 for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
9883 (*it).second->decrRef();
9888 * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
9889 * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
9890 * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
9891 * The caller is to deal with the resulting DataArrayInt.
9892 * \throw If the coordinate array is not set.
9893 * \throw If the nodal connectivity of the cells is not defined.
9894 * \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
9895 * \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
9897 * \sa DataArrayInt::sortEachPairToMakeALinkedList
9899 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
9901 checkFullyDefined();
9902 if(getMeshDimension()!=1)
9903 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
9905 // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
9906 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
9907 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
9908 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
9909 const int *d(_d->getConstPointer()), *dI(_dI->getConstPointer());
9910 const int *rD(_rD->getConstPointer()), *rDI(_rDI->getConstPointer());
9911 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
9912 const int * dsi(_dsi->getConstPointer());
9913 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dsii = _dsi->getIdsNotInRange(0,3);
9915 if (dsii->getNumberOfTuples())
9916 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
9918 int nc(getNumberOfCells());
9919 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> result(DataArrayInt::New());
9920 result->alloc(nc,1);
9922 // set of edges not used so far
9923 std::set<int> edgeSet;
9924 for (int i=0; i<nc; edgeSet.insert(i), i++);
9928 // while we have points with only one neighbor segments
9931 std::list<int> linePiece;
9932 // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
9933 for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
9935 // Fill the list forward (resp. backward) from the start segment:
9936 int activeSeg = startSeg;
9937 int prevPointId = -20;
9939 while (!edgeSet.empty())
9941 if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
9944 linePiece.push_back(activeSeg);
9946 linePiece.push_front(activeSeg);
9947 edgeSet.erase(activeSeg);
9950 int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
9951 ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
9952 if (dsi[ptId] == 1) // hitting the end of the line
9955 int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
9956 activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
9959 // Done, save final piece into DA:
9960 std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
9961 newIdx += linePiece.size();
9963 // identify next valid start segment (one which is not consumed)
9964 if(!edgeSet.empty())
9965 startSeg = *(edgeSet.begin());
9967 while (!edgeSet.empty());
9968 return result.retn();
9973 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
9975 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> nTmp(n); nTmp->incrRef();
9976 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>::const_iterator it(m.find(nTmp));
9978 throw INTERP_KERNEL::Exception("Internal error in remapping !");
9979 int v((*it).second);
9980 if(v==forbVal0 || v==forbVal1)
9982 if(std::find(isect.begin(),isect.end(),v)==isect.end())
9986 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
9991 bool presenceOfOn(false);
9992 for(int i=0;i<sz;i++)
9994 INTERP_KERNEL::ElementaryEdge *e(c[i]);
9995 if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
9997 IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
9998 IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
10000 return presenceOfOn;
10006 * 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.
10007 * 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.
10008 * 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.
10009 * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to avoid to have a non conform mesh.
10011 * \return int - the number of new nodes created (in most of cases 0).
10013 * \throw If \a this is not coherent.
10014 * \throw If \a this has not spaceDim equal to 2.
10015 * \throw If \a this has not meshDim equal to 2.
10016 * \throw If some subcells needed to be split are orphan.
10017 * \sa MEDCouplingUMesh::conformize2D
10019 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
10021 if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
10022 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
10023 desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
10024 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10025 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10026 if(midOpt==0 && midOptI==0)
10028 split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
10031 else if(midOpt!=0 && midOptI!=0)
10032 return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
10034 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
10038 * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
10039 * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
10040 * 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
10041 * 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).
10042 * 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.
10044 * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
10045 * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
10047 * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
10048 * This method expects that all nodes in \a this are not closer than \a eps.
10049 * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
10051 * \param [in] eps the relative error to detect merged edges.
10052 * \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
10053 * that the user is expected to deal with.
10055 * \throw If \a this is not coherent.
10056 * \throw If \a this has not spaceDim equal to 2.
10057 * \throw If \a this has not meshDim equal to 2.
10058 * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
10060 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
10062 static const int SPACEDIM=2;
10064 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10065 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10066 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
10067 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
10068 const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
10069 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
10070 const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
10071 int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
10072 std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
10073 std::vector<double> addCoo;
10074 BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
10075 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10076 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10077 for(int i=0;i<nDescCell;i++)
10079 std::vector<int> candidates;
10080 myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
10081 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
10084 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10085 INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
10086 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
10087 INTERP_KERNEL::MergePoints merge;
10088 INTERP_KERNEL::QuadraticPolygon c1,c2;
10089 e1->intersectWith(e2,merge,c1,c2);
10090 e1->decrRef(); e2->decrRef();
10091 if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
10092 overlapEdge[i].push_back(*it);
10093 if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
10094 overlapEdge[*it].push_back(i);
10097 // splitting done. sort intersect point in intersectEdge.
10098 std::vector< std::vector<int> > middle(nDescCell);
10099 int nbOf2DCellsToBeSplit(0);
10100 bool middleNeedsToBeUsed(false);
10101 std::vector<bool> cells2DToTreat(nDescCell,false);
10102 for(int i=0;i<nDescCell;i++)
10104 std::vector<int>& isect(intersectEdge[i]);
10105 int sz((int)isect.size());
10108 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10109 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
10110 e->sortSubNodesAbs(coords,isect);
10115 int idx0(rdi[i]),idx1(rdi[i+1]);
10117 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
10118 if(!cells2DToTreat[rd[idx0]])
10120 cells2DToTreat[rd[idx0]]=true;
10121 nbOf2DCellsToBeSplit++;
10123 // try to reuse at most eventual 'middle' of SEG3
10124 std::vector<int>& mid(middle[i]);
10125 mid.resize(sz+1,-1);
10126 if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
10128 middleNeedsToBeUsed=true;
10129 const std::vector<int>& candidates(overlapEdge[i]);
10130 std::vector<int> trueCandidates;
10131 for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
10132 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
10133 trueCandidates.push_back(*itc);
10134 int stNode(c[ci[i]+1]),endNode(isect[0]);
10135 for(int j=0;j<sz+1;j++)
10137 for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
10139 int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
10140 if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
10141 { mid[j]=*itc; break; }
10144 endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
10149 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
10150 if(nbOf2DCellsToBeSplit==0)
10153 int *retPtr(ret->getPointer());
10154 for(int i=0;i<nCell;i++)
10155 if(cells2DToTreat[i])
10158 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
10159 DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
10160 MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
10161 DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
10162 if(middleNeedsToBeUsed)
10163 { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
10164 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
10165 int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
10166 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.
10167 setPartOfMySelf(ret->begin(),ret->end(),*modif);
10169 bool areNodesMerged; int newNbOfNodes;
10170 if(nbOfNodesCreated!=0)
10171 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
10177 * 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.
10178 * 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).
10179 * 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
10180 * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
10181 * 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
10182 * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
10184 * 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
10185 * using new instance, idem for coordinates.
10187 * 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.
10189 * \return DataArrayInt * - The list of cellIds in \a this that have at least one edge colinearized.
10191 * \throw If \a this is not coherent.
10192 * \throw If \a this has not spaceDim equal to 2.
10193 * \throw If \a this has not meshDim equal to 2.
10195 * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
10197 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
10199 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
10201 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10202 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10203 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10204 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10205 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
10206 const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
10207 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
10208 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
10209 const double *coords(_coords->begin());
10210 int *newciptr(newci->getPointer());
10211 for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
10213 if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
10214 ret->pushBackSilent(i);
10215 newciptr[1]=newc->getNumberOfTuples();
10220 if(!appendedCoords->empty())
10222 appendedCoords->rearrange(2);
10223 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
10225 setCoords(newCoords);
10228 setConnectivity(newc,newci,true);
10233 * \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.
10234 * 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.
10235 * And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
10236 * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
10237 * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
10238 * \param [out] addCoo - nodes to be append at the end
10239 * \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.
10241 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
10242 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)
10244 static const int SPACEDIM=2;
10245 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10246 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10247 const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer());
10248 // Build BB tree of all edges in the tool mesh (second mesh)
10249 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
10250 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10251 int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
10252 intersectEdge1.resize(nDescCell1);
10253 colinear2.resize(nDescCell2);
10254 subDiv2.resize(nDescCell2);
10255 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
10257 std::vector<int> candidates1(1);
10258 int offset1(m1Desc->getNumberOfNodes());
10259 int offset2(offset1+m2Desc->getNumberOfNodes());
10260 for(int i=0;i<nDescCell1;i++) // for all edges in the first mesh
10262 std::vector<int> candidates2; // edges of mesh2 candidate for intersection
10263 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10264 if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
10266 std::map<INTERP_KERNEL::Node *,int> map1,map2;
10267 // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
10268 INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
10270 INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
10271 // 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
10272 // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
10273 std::set<INTERP_KERNEL::Node *> nodes;
10274 pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
10275 std::size_t szz(nodes.size());
10276 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
10277 std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
10278 for(std::size_t iii=0;iii<szz;iii++,itt++)
10279 { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
10280 // end of protection
10281 // Performs egde cutting:
10282 pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes);
10287 // Copy the edge (take only the two first points, ie discard quadratic point at this stage)
10288 intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i]+3);
10293 * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
10294 * It builds the descending connectivity of the two meshes, and then using a binary tree
10295 * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
10296 * Documentation about parameters colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
10298 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
10299 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
10300 MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
10301 std::vector<double>& addCoo,
10302 MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
10304 // Build desc connectivity
10305 desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
10306 desc2=DataArrayInt::New();
10307 descIndx2=DataArrayInt::New();
10308 revDesc2=DataArrayInt::New();
10309 revDescIndx2=DataArrayInt::New();
10310 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
10311 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
10312 m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
10313 m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
10314 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
10315 std::map<int,int> notUsedMap;
10316 Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap);
10317 m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
10318 m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
10322 * This method performs the 2nd step of Partition of 2D mesh.
10323 * This method has 4 inputs :
10324 * - a mesh 'm1' with meshDim==1 and a SpaceDim==2
10325 * - a mesh 'm2' with meshDim==1 and a SpaceDim==2
10326 * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
10327 * 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'
10328 * Nodes end up lying consecutively on a cutted edge.
10329 * \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.
10330 * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
10331 * \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.
10332 * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
10333 * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
10335 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
10336 const std::vector<double>& addCoo,
10337 const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
10339 int offset1=m1->getNumberOfNodes();
10340 int ncell=m2->getNumberOfCells();
10341 const int *c=m2->getNodalConnectivity()->getConstPointer();
10342 const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
10343 const double *coo=m2->getCoords()->getConstPointer();
10344 const double *cooBis=m1->getCoords()->getConstPointer();
10345 int offset2=offset1+m2->getNumberOfNodes();
10346 intersectEdge.resize(ncell);
10347 for(int i=0;i<ncell;i++,cI++)
10349 const std::vector<int>& divs=subDiv[i];
10350 int nnode=cI[1]-cI[0]-1;
10351 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
10352 std::map<INTERP_KERNEL::Node *, int> mapp22;
10353 for(int j=0;j<nnode;j++)
10355 INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
10356 int nnid=c[(*cI)+j+1];
10357 mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
10358 mapp22[nn]=nnid+offset1;
10360 INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
10361 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
10362 ((*it).second.first)->decrRef();
10363 std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
10364 std::map<INTERP_KERNEL::Node *,int> mapp3;
10365 for(std::size_t j=0;j<divs.size();j++)
10368 INTERP_KERNEL::Node *tmp=0;
10370 tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
10371 else if(id<offset2)
10372 tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
10374 tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
10378 e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
10379 for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
10386 * 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).
10387 * 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
10388 * with a plane. The result will be put in 'cut3DSuf' out parameter.
10389 * \param [in] cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
10390 * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
10391 * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
10392 * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
10393 * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
10394 * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
10395 * \param [in] desc is the descending connectivity 3DSurf->3DCurve
10396 * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
10397 * \param [out] cut3DSuf input/output param.
10399 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
10400 const int *nodal3DCurve, const int *nodalIndx3DCurve,
10401 const int *desc, const int *descIndx,
10402 std::vector< std::pair<int,int> >& cut3DSurf)
10404 std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
10405 int nbOf3DSurfCell=(int)cut3DSurf.size();
10406 for(int i=0;i<nbOf3DSurfCell;i++)
10408 std::vector<int> res;
10409 int offset=descIndx[i];
10410 int nbOfSeg=descIndx[i+1]-offset;
10411 for(int j=0;j<nbOfSeg;j++)
10413 int edgeId=desc[offset+j];
10414 int status=cut3DCurve[edgeId];
10418 res.push_back(status);
10421 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
10422 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
10430 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10436 std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
10437 std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
10440 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10444 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
10449 {// case when plane is on a multi colinear edge of a polyhedron
10450 if((int)res.size()==2*nbOfSeg)
10452 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
10455 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
10462 * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
10463 * 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).
10464 * 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
10465 * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
10466 * \param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
10467 * \param desc is the descending connectivity 3D->3DSurf
10468 * \param descIndx is the descending connectivity index 3D->3DSurf
10470 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
10471 const int *desc, const int *descIndx,
10472 DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
10474 checkFullyDefined();
10475 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10476 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
10477 const int *nodal3D=_nodal_connec->getConstPointer();
10478 const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
10479 int nbOfCells=getNumberOfCells();
10480 for(int i=0;i<nbOfCells;i++)
10482 std::map<int, std::set<int> > m;
10483 int offset=descIndx[i];
10484 int nbOfFaces=descIndx[i+1]-offset;
10487 for(int j=0;j<nbOfFaces;j++)
10489 const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
10490 if(p.first!=-1 && p.second!=-1)
10494 start=p.first; end=p.second;
10495 m[p.first].insert(p.second);
10496 m[p.second].insert(p.first);
10500 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
10501 int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
10502 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
10503 INTERP_KERNEL::NormalizedCellType cmsId;
10504 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
10505 start=tmp[0]; end=tmp[nbOfNodesSon-1];
10506 for(unsigned k=0;k<nbOfNodesSon;k++)
10508 m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
10509 m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
10516 std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
10520 std::map<int, std::set<int> >::const_iterator it=m.find(start);
10521 const std::set<int>& s=(*it).second;
10522 std::set<int> s2; s2.insert(prev);
10524 std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
10527 int val=*s3.begin();
10528 conn.push_back(start);
10535 conn.push_back(end);
10538 nodalRes->insertAtTheEnd(conn.begin(),conn.end());
10539 nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
10540 cellIds->pushBackSilent(i);
10546 * 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
10547 * 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
10548 * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
10549 * 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
10550 * 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.
10552 * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
10554 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
10556 std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
10559 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
10560 if(cm.getDimension()==2)
10562 const int *node=nodalConnBg+1;
10563 int startNode=*node++;
10564 double refX=coords[2*startNode];
10565 for(;node!=nodalConnEnd;node++)
10567 if(coords[2*(*node)]<refX)
10570 refX=coords[2*startNode];
10573 std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
10577 double angle0=-M_PI/2;
10582 double angleNext=0.;
10583 while(nextNode!=startNode)
10587 for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
10589 if(*node!=tmpOut.back() && *node!=prevNode)
10591 tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
10592 double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
10597 res=angle0-angleM+2.*M_PI;
10606 if(nextNode!=startNode)
10608 angle0=angleNext-M_PI;
10611 prevNode=tmpOut.back();
10612 tmpOut.push_back(nextNode);
10615 std::vector<int> tmp3(2*(sz-1));
10616 std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
10617 std::copy(nodalConnBg+1,nodalConnEnd,it);
10618 if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
10620 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10623 if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
10625 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10630 nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
10631 nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
10636 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10639 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10643 * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
10644 * 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.
10646 * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
10647 * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
10648 * \param [in,out] arr array in which the remove operation will be done.
10649 * \param [in,out] arrIndx array in the remove operation will modify
10650 * \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])
10651 * \return true if \b arr and \b arrIndx have been modified, false if not.
10653 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
10655 if(!arrIndx || !arr)
10656 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
10657 if(offsetForRemoval<0)
10658 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
10659 std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
10660 int nbOfGrps=arrIndx->getNumberOfTuples()-1;
10661 int *arrIPtr=arrIndx->getPointer();
10663 int previousArrI=0;
10664 const int *arrPtr=arr->getConstPointer();
10665 std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
10666 for(int i=0;i<nbOfGrps;i++,arrIPtr++)
10668 if(*arrIPtr-previousArrI>offsetForRemoval)
10670 for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
10672 if(s.find(*work)==s.end())
10673 arrOut.push_back(*work);
10676 previousArrI=*arrIPtr;
10677 *arrIPtr=(int)arrOut.size();
10679 if(arr->getNumberOfTuples()==(int)arrOut.size())
10681 arr->alloc((int)arrOut.size(),1);
10682 std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
10687 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10688 * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
10689 * The selection of extraction is done standardly in new2old format.
10690 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10692 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10693 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10694 * \param [in] arrIn arr origin array from which the extraction will be done.
10695 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10696 * \param [out] arrOut the resulting array
10697 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10698 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
10700 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10701 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10703 if(!arrIn || !arrIndxIn)
10704 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
10705 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10706 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10707 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
10708 std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
10709 const int *arrInPtr=arrIn->getConstPointer();
10710 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10711 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10713 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10714 int maxSizeOfArr=arrIn->getNumberOfTuples();
10715 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10716 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10717 arrIo->alloc((int)(sz+1),1);
10718 const int *idsIt=idsOfSelectBg;
10719 int *work=arrIo->getPointer();
10722 for(std::size_t i=0;i<sz;i++,work++,idsIt++)
10724 if(*idsIt>=0 && *idsIt<nbOfGrps)
10725 lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
10728 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10729 throw INTERP_KERNEL::Exception(oss.str().c_str());
10735 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
10736 oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
10737 throw INTERP_KERNEL::Exception(oss.str().c_str());
10740 arro->alloc(lgth,1);
10741 work=arro->getPointer();
10742 idsIt=idsOfSelectBg;
10743 for(std::size_t i=0;i<sz;i++,idsIt++)
10745 if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
10746 work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
10749 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
10750 oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10751 throw INTERP_KERNEL::Exception(oss.str().c_str());
10754 arrOut=arro.retn();
10755 arrIndexOut=arrIo.retn();
10759 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10760 * 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 ).
10761 * The selection of extraction is done standardly in new2old format.
10762 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10764 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10765 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10766 * \param [in] arrIn arr origin array from which the extraction will be done.
10767 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10768 * \param [out] arrOut the resulting array
10769 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10770 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
10772 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10773 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10775 if(!arrIn || !arrIndxIn)
10776 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
10777 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10778 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10779 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
10780 int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
10781 const int *arrInPtr=arrIn->getConstPointer();
10782 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10783 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10785 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10786 int maxSizeOfArr=arrIn->getNumberOfTuples();
10787 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10788 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10789 arrIo->alloc((int)(sz+1),1);
10790 int idsIt=idsOfSelectStart;
10791 int *work=arrIo->getPointer();
10794 for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
10796 if(idsIt>=0 && idsIt<nbOfGrps)
10797 lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
10800 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10801 throw INTERP_KERNEL::Exception(oss.str().c_str());
10807 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
10808 oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
10809 throw INTERP_KERNEL::Exception(oss.str().c_str());
10812 arro->alloc(lgth,1);
10813 work=arro->getPointer();
10814 idsIt=idsOfSelectStart;
10815 for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
10817 if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
10818 work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
10821 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
10822 oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10823 throw INTERP_KERNEL::Exception(oss.str().c_str());
10826 arrOut=arro.retn();
10827 arrIndexOut=arrIo.retn();
10831 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10832 * 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
10833 * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
10834 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
10836 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10837 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10838 * \param [in] arrIn arr origin array from which the extraction will be done.
10839 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10840 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
10841 * \param [in] srcArrIndex index array of \b srcArr
10842 * \param [out] arrOut the resulting array
10843 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10845 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
10847 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10848 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
10849 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10851 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10852 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
10853 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10854 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10855 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10856 std::vector<bool> v(nbOfTuples,true);
10858 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10859 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10860 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10862 if(*it>=0 && *it<nbOfTuples)
10865 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
10869 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
10870 throw INTERP_KERNEL::Exception(oss.str().c_str());
10873 srcArrIndexPtr=srcArrIndex->getConstPointer();
10874 arrIo->alloc(nbOfTuples+1,1);
10875 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
10876 const int *arrInPtr=arrIn->getConstPointer();
10877 const int *srcArrPtr=srcArr->getConstPointer();
10878 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
10879 int *arroPtr=arro->getPointer();
10880 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
10884 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
10885 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
10889 std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
10890 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
10891 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
10894 arrOut=arro.retn();
10895 arrIndexOut=arrIo.retn();
10899 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10900 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
10902 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10903 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10904 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
10905 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10906 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
10907 * \param [in] srcArrIndex index array of \b srcArr
10909 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
10911 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
10912 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
10914 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10915 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
10916 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10917 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10918 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10919 int *arrInOutPtr=arrInOut->getPointer();
10920 const int *srcArrPtr=srcArr->getConstPointer();
10921 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10923 if(*it>=0 && *it<nbOfTuples)
10925 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
10926 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
10929 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] !";
10930 throw INTERP_KERNEL::Exception(oss.str().c_str());
10935 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
10936 throw INTERP_KERNEL::Exception(oss.str().c_str());
10942 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
10943 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
10944 * 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]].
10945 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
10946 * A negative value in \b arrIn means that it is ignored.
10947 * 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.
10949 * \param [in] arrIn arr origin array from which the extraction will be done.
10950 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10951 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
10952 * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
10954 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
10956 int seed=0,nbOfDepthPeelingPerformed=0;
10957 return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
10961 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
10962 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
10963 * 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]].
10964 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
10965 * A negative value in \b arrIn means that it is ignored.
10966 * 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.
10967 * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
10968 * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
10969 * \param [in] arrIn arr origin array from which the extraction will be done.
10970 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10971 * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
10972 * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
10973 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
10974 * \sa MEDCouplingUMesh::partitionBySpreadZone
10976 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
10978 nbOfDepthPeelingPerformed=0;
10980 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
10981 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10984 DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
10988 std::vector<bool> fetched(nbOfTuples,false);
10989 return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
10992 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
10994 nbOfDepthPeelingPerformed=0;
10995 if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
10996 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
10997 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10998 std::vector<bool> fetched2(nbOfTuples,false);
11000 for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
11002 if(*seedElt>=0 && *seedElt<nbOfTuples)
11003 { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
11005 { 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()); }
11007 const int *arrInPtr=arrIn->getConstPointer();
11008 const int *arrIndxPtr=arrIndxIn->getConstPointer();
11009 int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
11010 std::vector<int> idsToFetch1(seedBg,seedEnd);
11011 std::vector<int> idsToFetch2;
11012 std::vector<int> *idsToFetch=&idsToFetch1;
11013 std::vector<int> *idsToFetchOther=&idsToFetch2;
11014 while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
11016 for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
11017 for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
11019 { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
11020 std::swap(idsToFetch,idsToFetchOther);
11021 idsToFetchOther->clear();
11022 nbOfDepthPeelingPerformed++;
11024 int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
11026 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
11027 int *retPtr=ret->getPointer();
11028 for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
11035 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11036 * 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
11037 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11038 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11040 * \param [in] start begin of set of ids of the input extraction (included)
11041 * \param [in] end end of set of ids of the input extraction (excluded)
11042 * \param [in] step step of the set of ids in range mode.
11043 * \param [in] arrIn arr origin array from which the extraction will be done.
11044 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11045 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11046 * \param [in] srcArrIndex index array of \b srcArr
11047 * \param [out] arrOut the resulting array
11048 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11050 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
11052 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11053 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11054 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11056 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11057 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
11058 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
11059 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
11060 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11062 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11063 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11064 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
11066 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11068 if(it>=0 && it<nbOfTuples)
11069 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
11072 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11073 throw INTERP_KERNEL::Exception(oss.str().c_str());
11076 srcArrIndexPtr=srcArrIndex->getConstPointer();
11077 arrIo->alloc(nbOfTuples+1,1);
11078 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11079 const int *arrInPtr=arrIn->getConstPointer();
11080 const int *srcArrPtr=srcArr->getConstPointer();
11081 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11082 int *arroPtr=arro->getPointer();
11083 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11085 int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
11088 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11089 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11093 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11094 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11097 arrOut=arro.retn();
11098 arrIndexOut=arrIo.retn();
11102 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11103 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11105 * \param [in] start begin of set of ids of the input extraction (included)
11106 * \param [in] end end of set of ids of the input extraction (excluded)
11107 * \param [in] step step of the set of ids in range mode.
11108 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11109 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11110 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11111 * \param [in] srcArrIndex index array of \b srcArr
11113 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11115 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11116 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11118 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11119 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
11120 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11121 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11122 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11123 int *arrInOutPtr=arrInOut->getPointer();
11124 const int *srcArrPtr=srcArr->getConstPointer();
11125 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
11127 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11129 if(it>=0 && it<nbOfTuples)
11131 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
11132 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
11135 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
11136 throw INTERP_KERNEL::Exception(oss.str().c_str());
11141 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11142 throw INTERP_KERNEL::Exception(oss.str().c_str());
11148 * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
11149 * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
11150 * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
11151 * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
11152 * The sum of measure field of returned mesh is equal to the sum of measure field of this.
11154 * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
11156 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
11158 checkFullyDefined();
11159 int mdim=getMeshDimension();
11160 int spaceDim=getSpaceDimension();
11162 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
11163 std::vector<DataArrayInt *> partition=partitionBySpreadZone();
11164 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
11165 std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
11166 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
11167 ret->setCoords(getCoords());
11168 ret->allocateCells((int)partition.size());
11170 for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
11172 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
11173 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
11177 cell=tmp->buildUnionOf2DMesh();
11180 cell=tmp->buildUnionOf3DMesh();
11183 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
11186 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
11189 ret->finishInsertingCells();
11194 * This method partitions \b this into contiguous zone.
11195 * This method only needs a well defined connectivity. Coordinates are not considered here.
11196 * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
11198 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
11200 int nbOfCellsCur=getNumberOfCells();
11201 std::vector<DataArrayInt *> ret;
11202 if(nbOfCellsCur<=0)
11204 DataArrayInt *neigh=0,*neighI=0;
11205 computeNeighborsOfCells(neigh,neighI);
11206 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
11207 std::vector<bool> fetchedCells(nbOfCellsCur,false);
11208 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
11210 while(seed<nbOfCellsCur)
11212 int nbOfPeelPerformed=0;
11213 ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
11214 seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
11216 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
11217 ret.push_back((*it).retn());
11222 * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
11223 * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
11225 * \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.
11226 * \return a newly allocated DataArrayInt to be managed by the caller.
11227 * \throw In case of \a code has not the right format (typically of size 3*n)
11229 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
11231 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
11232 std::size_t nb=code.size()/3;
11233 if(code.size()%3!=0)
11234 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
11235 ret->alloc((int)nb,2);
11236 int *retPtr=ret->getPointer();
11237 for(std::size_t i=0;i<nb;i++,retPtr+=2)
11239 retPtr[0]=code[3*i+2];
11240 retPtr[1]=code[3*i+2]+code[3*i+1];
11246 * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
11247 * All cells in \a this are expected to be linear 3D cells.
11248 * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
11249 * It leads to an increase to number of cells.
11250 * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
11251 * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints
11252 * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
11254 * \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.
11255 * For all other cells, the splitting policy will be ignored.
11256 * \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.
11257 * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
11258 * an id of old cell producing it. The caller is to delete this array using
11259 * decrRef() as it is no more needed.
11260 * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
11262 * \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
11263 * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
11265 * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
11266 * \throw If \a this is not fully constituted with linear 3D cells.
11267 * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
11269 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
11271 INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
11272 checkConnectivityFullyDefined();
11273 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
11274 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
11275 int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
11276 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
11277 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
11278 int *retPt(ret->getPointer());
11279 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
11280 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
11281 const int *oldc(_nodal_connec->begin());
11282 const int *oldci(_nodal_connec_index->begin());
11283 const double *coords(_coords->begin());
11284 for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
11286 std::vector<int> a; std::vector<double> b;
11287 INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
11288 std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
11289 const int *aa(&a[0]);
11292 for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
11294 *it=(-(*(it))-1+nbNodes);
11295 addPts->insertAtTheEnd(b.begin(),b.end());
11296 nbNodes+=(int)b.size()/3;
11298 for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
11299 newConn->insertAtTheEnd(aa,aa+4);
11301 if(!addPts->empty())
11303 addPts->rearrange(3);
11304 nbOfAdditionalPoints=addPts->getNumberOfTuples();
11305 addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
11306 ret0->setCoords(addPts);
11310 nbOfAdditionalPoints=0;
11311 ret0->setCoords(getCoords());
11313 ret0->setNodalConnectivity(newConn);
11315 ret->computeOffsets2();
11316 n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
11317 return ret0.retn();
11321 * 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).
11323 * \sa MEDCouplingUMesh::split2DCells
11325 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
11327 checkConnectivityFullyDefined();
11328 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
11329 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11330 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11331 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11332 int prevPosOfCi(ciPtr[0]);
11333 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11335 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
11336 *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
11337 for(int j=0;j<sz;j++)
11339 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
11340 for(int k=0;k<sz2;k++)
11341 *cPtr++=subPtr[offset2+k];
11343 *cPtr++=oldConn[prevPosOfCi+j+2];
11346 prevPosOfCi=ciPtr[1];
11347 ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11350 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
11351 _nodal_connec->decrRef();
11352 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
11355 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11361 int ret(nodesCnter++);
11363 e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
11364 addCoo.insertAtTheEnd(newPt,newPt+2);
11369 int InternalAddPointOriented(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11375 int ret(nodesCnter++);
11377 e->getMiddleOfPointsOriented(coo+2*startId,coo+2*endId,newPt);
11378 addCoo.insertAtTheEnd(newPt,newPt+2);
11386 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)
11389 int trueStart(start>=0?start:nbOfEdges+start);
11390 tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
11391 newConnOfCell->insertAtTheEnd(tmp,tmp+3);
11396 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11397 InternalAddPointOriented(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
11398 middles.push_back(tmp3+offset);
11401 middles.push_back(connBg[trueStart+nbOfEdges]);
11405 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)
11407 int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
11408 newConnOfCell->pushBackSilent(tmpEnd);
11413 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11414 InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11415 middles.push_back(tmp3+offset);
11418 middles.push_back(connBg[start+nbOfEdges]);
11422 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)
11424 // only the quadratic point to deal with:
11429 int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
11430 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11431 InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11432 middles.push_back(tmp3+offset);
11435 middles.push_back(connBg[start+nbOfEdges]);
11442 * 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 ) .
11443 * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
11445 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
11447 std::size_t sz(std::distance(connBg,connEnd));
11448 if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
11449 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
11451 INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
11452 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
11453 unsigned nbs(cm.getNumberOfSons2(connBg+1,sz));
11454 unsigned nbOfHit(0); // number of fusions operated
11455 int posBaseElt(0),posEndElt(0),nbOfTurn(0);
11456 const unsigned int maxNbOfHit = cm.isQuadratic() ? nbs-2 : nbs-3; // a quad cell is authorized to end up with only two edges, a linear one has to keep 3 at least
11457 INTERP_KERNEL::NormalizedCellType typeOfSon;
11458 std::vector<int> middles;
11460 for(;(nbOfTurn+nbOfHit)<nbs;nbOfTurn++)
11462 cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
11463 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
11464 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11465 posEndElt = posBaseElt+1;
11467 // Look backward first: are the final edges of the cells colinear with the first ones?
11468 // This initializes posBaseElt.
11471 for(unsigned i=1;i<nbs && nbOfHit<maxNbOfHit;i++) // 2nd condition is to avoid ending with a cell wih one single edge
11473 cm.fillSonCellNodalConnectivity2(nbs-i,connBg+1,sz,tmpConn,typeOfSon);
11474 INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11475 INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11476 bool isColinear=eint->areColinears();
11489 // Now move forward:
11490 const unsigned fwdStart = (nbOfTurn == 0 ? 0 : posBaseElt); // the first element to be inspected going forward
11491 for(unsigned j=fwdStart+1;j<nbs && nbOfHit<maxNbOfHit;j++) // 2nd condition is to avoid ending with a cell wih one single edge
11493 cm.fillSonCellNodalConnectivity2((int)j,connBg+1,sz,tmpConn,typeOfSon); // get edge #j's connectivity
11494 INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11495 INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11496 bool isColinear(eint->areColinears());
11508 //push [posBaseElt,posEndElt) in newConnOfCell using e
11509 // The if clauses below are (volontary) not mutually exclusive: on a quad cell with 2 edges, the end of the connectivity is also its begining!
11511 // at the begining of the connectivity (insert type)
11512 EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11513 else if((nbOfHit+nbOfTurn) != (nbs-1))
11515 EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11516 if ((nbOfHit+nbOfTurn) == (nbs-1))
11517 // at the end (only quad points to deal with)
11518 EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11519 posBaseElt=posEndElt;
11522 if(!middles.empty())
11523 newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
11528 * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
11530 * \return int - the number of new nodes created.
11531 * \sa MEDCouplingUMesh::split2DCells
11533 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
11536 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
11537 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11538 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
11539 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11540 const int *midPtr(mid->begin()),*midIPtr(midI->begin());
11541 const double *oldCoordsPtr(getCoords()->begin());
11542 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11543 int prevPosOfCi(ciPtr[0]);
11544 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11546 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
11547 for(int j=0;j<sz;j++)
11548 { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
11549 *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
11550 for(int j=0;j<sz;j++)//loop over subedges of oldConn
11552 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
11556 cPtr[1]=oldConn[prevPosOfCi+2+j];
11557 cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
11560 std::vector<INTERP_KERNEL::Node *> ns(3);
11561 ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
11562 ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
11563 ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
11564 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
11565 for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
11567 cPtr[1]=subPtr[offset2+k];
11568 cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
11570 int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
11572 { cPtr[1]=tmpEnd; }
11573 cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
11575 prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
11576 ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11579 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
11580 _nodal_connec->decrRef();
11581 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
11582 addCoo->rearrange(2);
11583 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
11585 return addCoo->getNumberOfTuples();
11588 void MEDCouplingUMesh::ComputeAllTypesInternal(std::set<INTERP_KERNEL::NormalizedCellType>& types, const DataArrayInt *nodalConnec, const DataArrayInt *nodalConnecIndex)
11590 if(nodalConnec && nodalConnecIndex)
11593 const int *conn(nodalConnec->getConstPointer()),*connIndex(nodalConnecIndex->getConstPointer());
11594 int nbOfElem(nodalConnecIndex->getNbOfElems()-1);
11596 for(const int *pt=connIndex;pt!=connIndex+nbOfElem;pt++)
11597 types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
11601 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
11602 _own_cell(true),_cell_id(-1),_nb_cell(0)
11607 _nb_cell=mesh->getNumberOfCells();
11611 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
11619 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
11620 _own_cell(false),_cell_id(bg-1),
11627 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
11630 if(_cell_id<_nb_cell)
11639 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
11645 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
11647 return new MEDCouplingUMeshCellByTypeIterator(_mesh);
11650 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
11656 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
11664 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
11670 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
11675 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
11680 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
11682 return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
11685 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
11690 _nb_cell=mesh->getNumberOfCells();
11694 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
11701 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
11703 const int *c=_mesh->getNodalConnectivity()->getConstPointer();
11704 const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
11705 if(_cell_id<_nb_cell)
11707 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
11708 int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
11709 int startId=_cell_id;
11710 _cell_id+=nbOfElems;
11711 return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
11717 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
11721 _conn=mesh->getNodalConnectivity()->getPointer();
11722 _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
11726 void MEDCouplingUMeshCell::next()
11728 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11733 _conn_lgth=_conn_indx[1]-_conn_indx[0];
11736 std::string MEDCouplingUMeshCell::repr() const
11738 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11740 std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
11742 std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
11746 return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
11749 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
11751 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11752 return (INTERP_KERNEL::NormalizedCellType)_conn[0];
11754 return INTERP_KERNEL::NORM_ERROR;
11757 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
11760 if(_conn_lgth!=NOTICABLE_FIRST_VAL)